You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hw-web/Admin.NET-v2/HW_PORTAL_抽离迁移指导.md

471 KiB

hw-portal 抽离迁移指导

1. 文档目的

  • 本文档基于仓库内源模块 ruoyi-portal 做静态分析,目标是指导其按“hw-portal 独立代码模块”方式迁移到当前 Admin.NET.NET 10项目。
  • 约束前提数据库表结构不变、SQL 不变、方法业务逻辑不变;允许替换工具类、框架胶水代码、统一返回包装、分页封装、鉴权与注解实现。
  • 当前仓库里还没有现成的 hw-portal 模块,因此本文档既是源码分析结果,也是后续抽离实施的基线。

2. 已确认事实与不确定点

  • 源模块路径:C:/D/WORK/NewP/Admin.NET-v2/ruoyi-portal
  • pom.xml 可直接确认:父工程 com.ruoyi:ruoyi:3.9.1,模块坐标 ruoyi-portal
  • 模块 pom.xml 直接声明的依赖只有:com.ruoyi:ruoyi-common
  • 由于 Spring Boot、MyBatis、Easy-ES 等版本由父 POM 继承,当前模块自身 pom.xml 里看不到完整版本;因此迁移指导按“版本无关 + 保留现有行为”编写。
  • 你补充说明源系统是 Spring Boot 3.5.8 + MyBatis + JDK17;源码中也确实出现了 jakarta.servlet,说明至少已经是 Jakarta 体系。
  • ruoyi-portal/src/test/java 下未发现测试源码,因此本次分析全部基于生产代码。

3. 模块总体画像

  • Java 源文件数:92
  • MyBatis XML 文件数:15
  • 参与源码附录的文件总数(含 pom.xml108
  • 涉及主要数据库表:hw_about_us_info_detail, hw_about_us_info, hw_web_visit_event, hw_web_visit_daily, hw_contact_us_info, hw_portal_config, hw_portal_config_type, hw_product_case_info, hw_product_info_detail, hw_product_info, hw_web_menu, hw_web, hw_web1, hw_web_document, hw_web_menu1
包/目录 文件数
controller 17
domain 16
domain/dto 6
domain/vo 1
mapper 15
search/convert 1
search/es/entity 1
search/es/mapper 1
search/service 1
search/service/impl 1
service 16
service/impl 16

3.1 功能分块

  • 门户前台聚合:HwPortalController
  • 后台内容维护:关于我们、联系我们、门户配置、配置类型、产品、案例、页面 JSON、菜单、资料文档。
  • 搜索MySQL 联合搜索 + Easy-ES 可选搜索 + 索引重建。
  • 官网分析:匿名埋点采集、日报聚合、看板排行。
  • 树结构数据:配置类型树、产品明细树、菜单树。

3.2 当前 Admin.NET 的推荐落点

  • 结合本仓库现状,最小阻力方案是把 hw-portal 放进 Admin.NET.Core
    • 实体建议放 Admin.NET/Admin.NET.Core/Entity/HwPortal/
    • 服务建议放 Admin.NET/Admin.NET.Core/Service/HwPortal/
    • DTO 建议放 Admin.NET/Admin.NET.Core/Service/HwPortal/Dto/
    • 若要完全隔离,也可以单独建 Admin.NET/Plugins/Admin.NET.Plugin.HwPortal/,但这会增加宿主注册、配置扫描、发布结构复杂度。
  • 从当前项目惯例看,IDynamicApiController + SqlSugarRepository/ISqlSugarClient + AdminResultProvider 是最贴合现有骨架的实现方式。
  • 因为你要求“SQL 不变”,所以仓储层不要把 XML SQL 改写成 SqlSugar LINQ优先保留原 SQL 文本,通过 ISqlSugarClient.Ado 执行。

4. 接口清单

控制器 方法名 HTTP 路径 方法签名 注解 主要调用链
HwAboutUsInfoController list GET /portal/aboutUsInfo/list public TableDataInfo list(HwAboutUsInfo hwAboutUsInfo) - hwAboutUsInfoService.selectHwAboutUsInfoList
HwAboutUsInfoController export POST /portal/aboutUsInfo/export public void export(HttpServletResponse response, HwAboutUsInfo hwAboutUsInfo) RepeatSubmit hwAboutUsInfoService.selectHwAboutUsInfoList
HwAboutUsInfoController getInfo GET /portal/aboutUsInfo/{aboutUsInfoId} public AjaxResult getInfo(@PathVariable("aboutUsInfoId") Long aboutUsInfoId) - hwAboutUsInfoService.selectHwAboutUsInfoByAboutUsInfoId
HwAboutUsInfoController add POST /portal/aboutUsInfo public AjaxResult add(@RequestBody HwAboutUsInfo hwAboutUsInfo) RepeatSubmit hwAboutUsInfoService.insertHwAboutUsInfo
HwAboutUsInfoController edit PUT /portal/aboutUsInfo public AjaxResult edit(@RequestBody HwAboutUsInfo hwAboutUsInfo) RepeatSubmit hwAboutUsInfoService.updateHwAboutUsInfo
HwAboutUsInfoController remove DELETE /portal/aboutUsInfo/{aboutUsInfoIds} public AjaxResult remove(@PathVariable Long[] aboutUsInfoIds) RepeatSubmit hwAboutUsInfoService.deleteHwAboutUsInfoByAboutUsInfoIds
HwAboutUsInfoDetailController list GET /portal/aboutUsInfoDetail/list public TableDataInfo list(HwAboutUsInfoDetail hwAboutUsInfoDetail) - hwAboutUsInfoDetailService.selectHwAboutUsInfoDetailList
HwAboutUsInfoDetailController export POST /portal/aboutUsInfoDetail/export public void export(HttpServletResponse response, HwAboutUsInfoDetail hwAboutUsInfoDetail) RepeatSubmit hwAboutUsInfoDetailService.selectHwAboutUsInfoDetailList
HwAboutUsInfoDetailController getInfo GET /portal/aboutUsInfoDetail/{usInfoDetailId} public AjaxResult getInfo(@PathVariable("usInfoDetailId") Long usInfoDetailId) - hwAboutUsInfoDetailService.selectHwAboutUsInfoDetailByUsInfoDetailId
HwAboutUsInfoDetailController add POST /portal/aboutUsInfoDetail public AjaxResult add(@RequestBody HwAboutUsInfoDetail hwAboutUsInfoDetail) RepeatSubmit hwAboutUsInfoDetailService.insertHwAboutUsInfoDetail
HwAboutUsInfoDetailController edit PUT /portal/aboutUsInfoDetail public AjaxResult edit(@RequestBody HwAboutUsInfoDetail hwAboutUsInfoDetail) RepeatSubmit hwAboutUsInfoDetailService.updateHwAboutUsInfoDetail
HwAboutUsInfoDetailController remove DELETE /portal/aboutUsInfoDetail/{usInfoDetailIds} public AjaxResult remove(@PathVariable Long[] usInfoDetailIds) RepeatSubmit hwAboutUsInfoDetailService.deleteHwAboutUsInfoDetailByUsInfoDetailIds
HwAnalyticsController collect POST /portal/analytics/collect public AjaxResult collect(@RequestBody(required = false) String body, HttpServletRequest request) Anonymous / RateLimiter hwAnalyticsService.collect
HwAnalyticsController dashboard GET /portal/analytics/dashboard public AjaxResult dashboard(@RequestParam(value = "statDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate statDate, @RequestParam(value = "top", required = false) Integer top) Log hwAnalyticsService.getDashboard
HwAnalyticsController refreshDaily POST /portal/analytics/refreshDaily public AjaxResult refreshDaily(@RequestParam(value = "statDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate statDate) Log hwAnalyticsService.refreshDailyStat
HwContactUsInfoController list GET /portal/contactUsInfo/list public TableDataInfo list(HwContactUsInfo hwContactUsInfo) - hwContactUsInfoService.selectHwContactUsInfoList
HwContactUsInfoController export POST /portal/contactUsInfo/export public void export(HttpServletResponse response, HwContactUsInfo hwContactUsInfo) RepeatSubmit hwContactUsInfoService.selectHwContactUsInfoList
HwContactUsInfoController getInfo GET /portal/contactUsInfo/{contactUsInfoId} public AjaxResult getInfo(@PathVariable("contactUsInfoId") Long contactUsInfoId) - hwContactUsInfoService.selectHwContactUsInfoByContactUsInfoId
HwContactUsInfoController add POST /portal/contactUsInfo public AjaxResult add(@RequestBody HwContactUsInfo hwContactUsInfo) RepeatSubmit hwContactUsInfoService.insertHwContactUsInfo
HwContactUsInfoController edit PUT /portal/contactUsInfo public AjaxResult edit(@RequestBody HwContactUsInfo hwContactUsInfo) RepeatSubmit hwContactUsInfoService.updateHwContactUsInfo
HwContactUsInfoController remove DELETE /portal/contactUsInfo/{contactUsInfoIds} public AjaxResult remove(@PathVariable Long[] contactUsInfoIds) RepeatSubmit hwContactUsInfoService.deleteHwContactUsInfoByContactUsInfoIds
HwPortalConfigController list GET /portal/portalConfig/list public TableDataInfo list(HwPortalConfig hwPortalConfig) - hwPortalConfigService.selectHwPortalConfigJoinList
HwPortalConfigController export POST /portal/portalConfig/export public void export(HttpServletResponse response, HwPortalConfig hwPortalConfig) RepeatSubmit hwPortalConfigService.selectHwPortalConfigList
HwPortalConfigController getInfo GET /portal/portalConfig/{portalConfigId} public AjaxResult getInfo(@PathVariable("portalConfigId") Long portalConfigId) - hwPortalConfigService.selectHwPortalConfigByPortalConfigId
HwPortalConfigController add POST /portal/portalConfig public AjaxResult add(@RequestBody HwPortalConfig hwPortalConfig) RepeatSubmit hwPortalConfigService.insertHwPortalConfig
HwPortalConfigController edit PUT /portal/portalConfig public AjaxResult edit(@RequestBody HwPortalConfig hwPortalConfig) RepeatSubmit hwPortalConfigService.updateHwPortalConfig
HwPortalConfigController remove DELETE /portal/portalConfig/{portalConfigIds} public AjaxResult remove(@PathVariable Long[] portalConfigIds) RepeatSubmit hwPortalConfigService.deleteHwPortalConfigByPortalConfigIds
HwPortalConfigController portalConfigTypeTree GET /portal/portalConfig/portalConfigTypeTree public AjaxResult portalConfigTypeTree(HwPortalConfigType hwPortalConfigType) - hwPortalConfigTypeService.selectPortalConfigTypeTreeList
HwPortalConfigTypeController list GET /portal/portalConfigType/list public AjaxResult list(HwPortalConfigType hwPortalConfigType) - hwPortalConfigTypeService.selectHwPortalConfigTypeList
HwPortalConfigTypeController export POST /portal/portalConfigType/export public void export(HttpServletResponse response, HwPortalConfigType hwPortalConfigType) RepeatSubmit hwPortalConfigTypeService.selectHwPortalConfigTypeList
HwPortalConfigTypeController getInfo GET /portal/portalConfigType/{configTypeId} public AjaxResult getInfo(@PathVariable("configTypeId") Long configTypeId) - hwPortalConfigTypeService.selectHwPortalConfigTypeByConfigTypeId
HwPortalConfigTypeController add POST /portal/portalConfigType public AjaxResult add(@RequestBody HwPortalConfigType hwPortalConfigType) RepeatSubmit hwPortalConfigTypeService.insertHwPortalConfigType
HwPortalConfigTypeController edit PUT /portal/portalConfigType public AjaxResult edit(@RequestBody HwPortalConfigType hwPortalConfigType) RepeatSubmit hwPortalConfigTypeService.updateHwPortalConfigType
HwPortalConfigTypeController remove DELETE /portal/portalConfigType/{configTypeIds} public AjaxResult remove(@PathVariable Long[] configTypeIds) RepeatSubmit hwPortalConfigTypeService.deleteHwPortalConfigTypeByConfigTypeIds
HwPortalController getPortalConfigList GET /portal/portal/getPortalConfigList public TableDataInfo getPortalConfigList(HwPortalConfig hwPortalConfig) - hwPortalConfigService.selectHwPortalConfigList
HwPortalController getPortalConfigTypeList GET /portal/portal/getPortalConfigTypeList public TableDataInfo getPortalConfigTypeList(HwPortalConfigType hwPortalConfigType) - hwPortalConfigTypeService.selectHwPortalConfigTypeList
HwPortalController selectConfigTypeList GET /portal/portal/selectConfigTypeList public TableDataInfo selectConfigTypeList(HwPortalConfigType hwPortalConfigType) - hwPortalConfigTypeService.selectConfigTypeList
HwPortalController getHomeCaseTitleList GET /portal/portal/getHomeCaseTitleList public TableDataInfo getHomeCaseTitleList(HwPortalConfigType hwPortalConfigType) - hwPortalConfigTypeService.selectHwPortalConfigTypeList
HwPortalController getTypicalHomeCaseInfo GET /portal/portal/getTypicalHomeCaseInfo public AjaxResult getTypicalHomeCaseInfo(HwProductCaseInfo queryProductCaseInfo) - hwProductCaseInfoService.getTypicalHomeCaseInfo
HwPortalController addContactUsInfo POST /portal/portal/addContactUsInfo public AjaxResult addContactUsInfo(@RequestBody HwContactUsInfo hwContactUsInfo) RepeatSubmit hwContactUsInfoService.insertHwContactUsInfo
HwPortalController getProductCenterProductInfos GET /portal/portal/getProductCenterProductInfos public AjaxResult getProductCenterProductInfos(HwProductInfo hwProductInfo) - productInfoService.selectHwProductInfoJoinDetailList
HwPortalController getProductCenterProductDetailInfos GET /portal/portal/getProductCenterProductDetailInfos public AjaxResult getProductCenterProductDetailInfos(HwProductInfoDetail hwProductInfoDetail) - hwProductInfoDetailService.selectHwProductInfoDetailList
HwPortalController getCaseCenterCaseInfos GET /portal/portal/getCaseCenterCaseInfos public AjaxResult getCaseCenterCaseInfos(HwProductCaseInfo hwProductCaseInfo) - hwProductCaseInfoService.selectHwProductCaseInfoList
HwPortalController getCaseCenterCaseInfo GET /portal/portal/getCaseCenterCaseInfo/{caseInfoId} public AjaxResult getCaseCenterCaseInfo(@PathVariable("caseInfoId") Long caseInfoId) - hwProductCaseInfoService.selectHwProductCaseInfoByCaseInfoId
HwPortalController getAboutUsInfo GET /portal/portal/getAboutUsInfo public AjaxResult getAboutUsInfo(HwAboutUsInfo hwAboutUsInfo) - hwAboutUsInfoService.selectHwAboutUsInfoList
HwPortalController getAboutUsInfoDetails GET /portal/portal/getAboutUsInfoDetails public AjaxResult getAboutUsInfoDetails(HwAboutUsInfoDetail hwAboutUsInfoDetail) - hwAboutUsInfoDetailService.selectHwAboutUsInfoDetailList
HwProductCaseInfoController list GET /portal/productCaseInfo/list public TableDataInfo list(HwProductCaseInfo hwProductCaseInfo) - hwProductCaseInfoService.selectHwProductCaseInfoList
HwProductCaseInfoController export POST /portal/productCaseInfo/export public void export(HttpServletResponse response, HwProductCaseInfo hwProductCaseInfo) RepeatSubmit hwProductCaseInfoService.selectHwProductCaseInfoList
HwProductCaseInfoController getInfo GET /portal/productCaseInfo/{caseInfoId} public AjaxResult getInfo(@PathVariable("caseInfoId") Long caseInfoId) - hwProductCaseInfoService.selectHwProductCaseInfoByCaseInfoId
HwProductCaseInfoController add POST /portal/productCaseInfo public AjaxResult add(@RequestBody HwProductCaseInfo hwProductCaseInfo) RepeatSubmit hwProductCaseInfoService.insertHwProductCaseInfo
HwProductCaseInfoController edit PUT /portal/productCaseInfo public AjaxResult edit(@RequestBody HwProductCaseInfo hwProductCaseInfo) RepeatSubmit hwProductCaseInfoService.updateHwProductCaseInfo
HwProductCaseInfoController remove DELETE /portal/productCaseInfo/{caseInfoIds} public AjaxResult remove(@PathVariable Long[] caseInfoIds) RepeatSubmit hwProductCaseInfoService.deleteHwProductCaseInfoByCaseInfoIds
HwProductCaseInfoController portalConfigTypeTree GET /portal/productCaseInfo/portalConfigTypeTree public AjaxResult portalConfigTypeTree(HwPortalConfigType hwPortalConfigType) - hwPortalConfigTypeService.selectPortalConfigTypeTreeList
HwProductInfoController list GET /portal/productInfo/list public TableDataInfo list(HwProductInfo hwProductInfo) - hwProductInfoService.selectHwProductInfoJoinList
HwProductInfoController export POST /portal/productInfo/export public void export(HttpServletResponse response, HwProductInfo hwProductInfo) RepeatSubmit hwProductInfoService.selectHwProductInfoList
HwProductInfoController getInfo GET /portal/productInfo/{productInfoId} public AjaxResult getInfo(@PathVariable("productInfoId") Long productInfoId) - hwProductInfoService.selectHwProductInfoByProductInfoId
HwProductInfoController add POST /portal/productInfo public AjaxResult add(@RequestBody HwProductInfo hwProductInfo) RepeatSubmit hwProductInfoService.insertHwProductInfo
HwProductInfoController edit PUT /portal/productInfo public AjaxResult edit(@RequestBody HwProductInfo hwProductInfo) RepeatSubmit hwProductInfoService.updateHwProductInfo
HwProductInfoController remove DELETE /portal/productInfo/{productInfoIds} public AjaxResult remove(@PathVariable Long[] productInfoIds) RepeatSubmit hwProductInfoService.deleteHwProductInfoByProductInfoIds
HwProductInfoController portalConfigTypeTree GET /portal/productInfo/portalConfigTypeTree public AjaxResult portalConfigTypeTree(HwPortalConfigType hwPortalConfigType) - hwPortalConfigTypeService.selectPortalConfigTypeTreeList
HwProductInfoDetailController list GET /portal/productInfoDetail/list public AjaxResult list(HwProductInfoDetail hwProductInfoDetail) - hwProductInfoDetailService.selectHwProductInfoDetailList
HwProductInfoDetailController export POST /portal/productInfoDetail/export public void export(HttpServletResponse response, HwProductInfoDetail hwProductInfoDetail) RepeatSubmit hwProductInfoDetailService.selectHwProductInfoDetailList
HwProductInfoDetailController getInfo GET /portal/productInfoDetail/{productInfoDetailId} public AjaxResult getInfo(@PathVariable("productInfoDetailId") Long productInfoDetailId) - hwProductInfoDetailService.selectHwProductInfoDetailByProductInfoDetailId
HwProductInfoDetailController add POST /portal/productInfoDetail public AjaxResult add(@RequestBody HwProductInfoDetail hwProductInfoDetail) RepeatSubmit hwProductInfoDetailService.insertHwProductInfoDetail
HwProductInfoDetailController edit PUT /portal/productInfoDetail public AjaxResult edit(@RequestBody HwProductInfoDetail hwProductInfoDetail) RepeatSubmit hwProductInfoDetailService.updateHwProductInfoDetail
HwProductInfoDetailController remove DELETE /portal/productInfoDetail/{productInfoDetailIds} public AjaxResult remove(@PathVariable Long[] productInfoDetailIds) RepeatSubmit hwProductInfoDetailService.deleteHwProductInfoDetailByProductInfoDetailIds
HwSearchAdminController rebuild POST /portal/search/admin/rebuild public AjaxResult rebuild() Log hwSearchRebuildService.rebuildAll
HwSearchController search GET /portal/search public AjaxResult search(@RequestParam("keyword") String keyword, @RequestParam(value = "pageNum", required = false) Integer pageNum, @RequestParam(value = "pageSize", required = false) Integer pageSize) RateLimiter hwSearchService.search
HwSearchController editSearch GET /portal/search/edit public AjaxResult editSearch(@RequestParam("keyword") String keyword, @RequestParam(value = "pageNum", required = false) Integer pageNum, @RequestParam(value = "pageSize", required = false) Integer pageSize) RateLimiter hwSearchService.searchForEdit
HwWebController list GET /portal/hwWeb/list public TableDataInfo list(HwWeb hwWeb) - hwWebService.selectHwWebList
HwWebController export POST /portal/hwWeb/export public void export(HttpServletResponse response, HwWeb hwWeb) RepeatSubmit hwWebService.selectHwWebList
HwWebController getInfo GET /portal/hwWeb/{webCode} public AjaxResult getInfo(@PathVariable("webCode") Long webCode) - hwWebService.selectHwWebByWebcode
HwWebController add POST /portal/hwWeb public AjaxResult add(@RequestBody HwWeb hwWeb) RepeatSubmit hwWebService.insertHwWeb
HwWebController edit PUT /portal/hwWeb public AjaxResult edit(@RequestBody HwWeb hwWeb) RepeatSubmit hwWebService.updateHwWeb
HwWebController remove DELETE /portal/hwWeb/{webIds} public AjaxResult remove(@PathVariable Long[] webIds) RepeatSubmit hwWebService.deleteHwWebByWebIds
HwWebController getHwWebList GET /portal/hwWeb/getHwWebList public AjaxResult getHwWebList(HwWeb HwWeb) - hwWebService.selectHwWebList
HwWebController1 list GET /portal/hwWeb1/list public TableDataInfo list(HwWeb1 HwWeb1) - -
HwWebController1 export POST /portal/hwWeb1/export public void export(HttpServletResponse response, HwWeb1 HwWeb1) RepeatSubmit -
HwWebController1 getInfo GET /portal/hwWeb1/{webCode} public AjaxResult getInfo(@PathVariable("webCode") Long webCode) - -
HwWebController1 add POST /portal/hwWeb1 public AjaxResult add(@RequestBody HwWeb1 HwWeb1) RepeatSubmit -
HwWebController1 edit PUT /portal/hwWeb1 public AjaxResult edit(@RequestBody HwWeb1 HwWeb1) RepeatSubmit -
HwWebController1 remove DELETE /portal/hwWeb1/{webIds} public AjaxResult remove(@PathVariable Long[] webIds) RepeatSubmit -
HwWebController1 getHwWeb1List GET /portal/hwWeb1/getHwWeb1List public AjaxResult getHwWeb1List(HwWeb1 HwWeb1) - -
HwWebDocumentController list GET /portal/hwWebDocument/list public TableDataInfo list(HwWebDocument hwWebDocument) - hwWebDocumentService.selectHwWebDocumentList
HwWebDocumentController export POST /portal/hwWebDocument/export public void export(HttpServletResponse response, HwWebDocument hwWebDocument) RepeatSubmit hwWebDocumentService.selectHwWebDocumentList
HwWebDocumentController getInfo GET /portal/hwWebDocument/{documentId} public AjaxResult getInfo(@PathVariable("documentId") String documentId) - hwWebDocumentService.selectHwWebDocumentByDocumentId
HwWebDocumentController add POST /portal/hwWebDocument public AjaxResult add(@RequestBody HwWebDocument hwWebDocument) RepeatSubmit hwWebDocumentService.insertHwWebDocument
HwWebDocumentController edit PUT /portal/hwWebDocument public AjaxResult edit(@RequestBody HwWebDocument hwWebDocument) RepeatSubmit hwWebDocumentService.updateHwWebDocument
HwWebDocumentController remove DELETE /portal/hwWebDocument/{documentIds} public AjaxResult remove(@PathVariable String[] documentIds) RepeatSubmit hwWebDocumentService.deleteHwWebDocumentByDocumentIds
HwWebDocumentController getSecureDocumentAddress POST /portal/hwWebDocument/getSecureDocumentAddress public AjaxResult getSecureDocumentAddress(@RequestBody SecureDocumentRequest request) RepeatSubmit hwWebDocumentService.verifyAndGetDocumentAddress
HwWebMenuController list GET /portal/hwWebMenu/list public AjaxResult list(HwWebMenu hwWebMenu) - hwWebMenuService.selectHwWebMenuList
HwWebMenuController export POST /portal/hwWebMenu/export public void export(HttpServletResponse response, HwWebMenu hwWebMenu) RepeatSubmit hwWebMenuService.selectHwWebMenuList
HwWebMenuController getInfo GET /portal/hwWebMenu/{webMenuId} public AjaxResult getInfo(@PathVariable("webMenuId") Long webMenuId) - hwWebMenuService.selectHwWebMenuByWebMenuId
HwWebMenuController add POST /portal/hwWebMenu public AjaxResult add(@RequestBody HwWebMenu hwWebMenu) RepeatSubmit hwWebMenuService.insertHwWebMenu
HwWebMenuController edit PUT /portal/hwWebMenu public AjaxResult edit(@RequestBody HwWebMenu hwWebMenu) RepeatSubmit hwWebMenuService.updateHwWebMenu
HwWebMenuController remove DELETE /portal/hwWebMenu/{webMenuIds} public AjaxResult remove(@PathVariable Long[] webMenuIds) RepeatSubmit hwWebMenuService.deleteHwWebMenuByWebMenuIds
HwWebMenuController selectMenuTree GET /portal/hwWebMenu/selectMenuTree public AjaxResult selectMenuTree(HwWebMenu hwWebMenu) - hwWebMenuService.selectMenuTree
HwWebMenuController1 list GET /portal/hwWebMenu1/list public AjaxResult list(HwWebMenu1 hwWebMenu1) - -
HwWebMenuController1 export POST /portal/hwWebMenu1/export public void export(HttpServletResponse response, HwWebMenu1 hwWebMenu1) RepeatSubmit -
HwWebMenuController1 getInfo GET /portal/hwWebMenu1/{webMenuId} public AjaxResult getInfo(@PathVariable("webMenuId") Long webMenuId) - -
HwWebMenuController1 add POST /portal/hwWebMenu1 public AjaxResult add(@RequestBody HwWebMenu1 hwWebMenu1) RepeatSubmit -
HwWebMenuController1 edit PUT /portal/hwWebMenu1 public AjaxResult edit(@RequestBody HwWebMenu1 hwWebMenu1) RepeatSubmit -
HwWebMenuController1 remove DELETE /portal/hwWebMenu1/{webMenuIds} public AjaxResult remove(@PathVariable Long[] webMenuIds) RepeatSubmit -
HwWebMenuController1 selectMenuTree GET /portal/hwWebMenu1/selectMenuTree public AjaxResult selectMenuTree(HwWebMenu1 hwWebMenu1) - -

5. 服务接口与 Mapper 方法

5.1 Service 接口

接口 方法 返回值 参数 源文件
IHwAboutUsInfoDetailService deleteHwAboutUsInfoDetailByUsInfoDetailId public int Long usInfoDetailId src/main/java/com/ruoyi/portal/service/IHwAboutUsInfoDetailService.java
IHwAboutUsInfoDetailService deleteHwAboutUsInfoDetailByUsInfoDetailIds public int Long[] usInfoDetailIds src/main/java/com/ruoyi/portal/service/IHwAboutUsInfoDetailService.java
IHwAboutUsInfoDetailService insertHwAboutUsInfoDetail public int HwAboutUsInfoDetail hwAboutUsInfoDetail src/main/java/com/ruoyi/portal/service/IHwAboutUsInfoDetailService.java
IHwAboutUsInfoDetailService selectHwAboutUsInfoDetailByUsInfoDetailId public HwAboutUsInfoDetail Long usInfoDetailId src/main/java/com/ruoyi/portal/service/IHwAboutUsInfoDetailService.java
IHwAboutUsInfoDetailService selectHwAboutUsInfoDetailList public List<HwAboutUsInfoDetail> HwAboutUsInfoDetail hwAboutUsInfoDetail src/main/java/com/ruoyi/portal/service/IHwAboutUsInfoDetailService.java
IHwAboutUsInfoDetailService updateHwAboutUsInfoDetail public int HwAboutUsInfoDetail hwAboutUsInfoDetail src/main/java/com/ruoyi/portal/service/IHwAboutUsInfoDetailService.java
IHwAboutUsInfoService deleteHwAboutUsInfoByAboutUsInfoId public int Long aboutUsInfoId src/main/java/com/ruoyi/portal/service/IHwAboutUsInfoService.java
IHwAboutUsInfoService deleteHwAboutUsInfoByAboutUsInfoIds public int Long[] aboutUsInfoIds src/main/java/com/ruoyi/portal/service/IHwAboutUsInfoService.java
IHwAboutUsInfoService insertHwAboutUsInfo public int HwAboutUsInfo hwAboutUsInfo src/main/java/com/ruoyi/portal/service/IHwAboutUsInfoService.java
IHwAboutUsInfoService selectHwAboutUsInfoByAboutUsInfoId public HwAboutUsInfo Long aboutUsInfoId src/main/java/com/ruoyi/portal/service/IHwAboutUsInfoService.java
IHwAboutUsInfoService selectHwAboutUsInfoList public List<HwAboutUsInfo> HwAboutUsInfo hwAboutUsInfo src/main/java/com/ruoyi/portal/service/IHwAboutUsInfoService.java
IHwAboutUsInfoService updateHwAboutUsInfo public int HwAboutUsInfo hwAboutUsInfo src/main/java/com/ruoyi/portal/service/IHwAboutUsInfoService.java
IHwAnalyticsService collect void AnalyticsCollectRequest request, String requestIp, String requestUserAgent src/main/java/com/ruoyi/portal/service/IHwAnalyticsService.java
IHwAnalyticsService getDashboard AnalyticsDashboardDTO LocalDate statDate, Integer rankLimit src/main/java/com/ruoyi/portal/service/IHwAnalyticsService.java
IHwAnalyticsService refreshDailyStat void LocalDate statDate src/main/java/com/ruoyi/portal/service/IHwAnalyticsService.java
IHwContactUsInfoService deleteHwContactUsInfoByContactUsInfoId public int Long contactUsInfoId src/main/java/com/ruoyi/portal/service/IHwContactUsInfoService.java
IHwContactUsInfoService deleteHwContactUsInfoByContactUsInfoIds public int Long[] contactUsInfoIds src/main/java/com/ruoyi/portal/service/IHwContactUsInfoService.java
IHwContactUsInfoService insertHwContactUsInfo public int HwContactUsInfo hwContactUsInfo src/main/java/com/ruoyi/portal/service/IHwContactUsInfoService.java
IHwContactUsInfoService selectHwContactUsInfoByContactUsInfoId public HwContactUsInfo Long contactUsInfoId src/main/java/com/ruoyi/portal/service/IHwContactUsInfoService.java
IHwContactUsInfoService selectHwContactUsInfoList public List<HwContactUsInfo> HwContactUsInfo hwContactUsInfo src/main/java/com/ruoyi/portal/service/IHwContactUsInfoService.java
IHwContactUsInfoService updateHwContactUsInfo public int HwContactUsInfo hwContactUsInfo src/main/java/com/ruoyi/portal/service/IHwContactUsInfoService.java
IHwPortalConfigService deleteHwPortalConfigByPortalConfigId public int Long portalConfigId src/main/java/com/ruoyi/portal/service/IHwPortalConfigService.java
IHwPortalConfigService deleteHwPortalConfigByPortalConfigIds public int Long[] portalConfigIds src/main/java/com/ruoyi/portal/service/IHwPortalConfigService.java
IHwPortalConfigService insertHwPortalConfig public int HwPortalConfig hwPortalConfig src/main/java/com/ruoyi/portal/service/IHwPortalConfigService.java
IHwPortalConfigService selectHwPortalConfigByPortalConfigId public HwPortalConfig Long portalConfigId src/main/java/com/ruoyi/portal/service/IHwPortalConfigService.java
IHwPortalConfigService selectHwPortalConfigJoinList public List<HwPortalConfig> HwPortalConfig hwPortalConfig src/main/java/com/ruoyi/portal/service/IHwPortalConfigService.java
IHwPortalConfigService selectHwPortalConfigList public List<HwPortalConfig> HwPortalConfig hwPortalConfig src/main/java/com/ruoyi/portal/service/IHwPortalConfigService.java
IHwPortalConfigService updateHwPortalConfig public int HwPortalConfig hwPortalConfig src/main/java/com/ruoyi/portal/service/IHwPortalConfigService.java
IHwPortalConfigTypeService buildPortalConfigTypeTree public List<HwPortalConfigType> List<HwPortalConfigType> portalConfigTypes src/main/java/com/ruoyi/portal/service/IHwPortalConfigTypeService.java
IHwPortalConfigTypeService buildPortalConfigTypeTreeSelect public List<TreeSelect> List<HwPortalConfigType> portalConfigTypes src/main/java/com/ruoyi/portal/service/IHwPortalConfigTypeService.java
IHwPortalConfigTypeService deleteHwPortalConfigTypeByConfigTypeId public int Long configTypeId src/main/java/com/ruoyi/portal/service/IHwPortalConfigTypeService.java
IHwPortalConfigTypeService deleteHwPortalConfigTypeByConfigTypeIds public int Long[] configTypeIds src/main/java/com/ruoyi/portal/service/IHwPortalConfigTypeService.java
IHwPortalConfigTypeService insertHwPortalConfigType public int HwPortalConfigType hwPortalConfigType src/main/java/com/ruoyi/portal/service/IHwPortalConfigTypeService.java
IHwPortalConfigTypeService selectConfigTypeList public List<HwPortalConfigType> HwPortalConfigType hwPortalConfigType src/main/java/com/ruoyi/portal/service/IHwPortalConfigTypeService.java
IHwPortalConfigTypeService selectHwPortalConfigTypeByConfigTypeId public HwPortalConfigType Long configTypeId src/main/java/com/ruoyi/portal/service/IHwPortalConfigTypeService.java
IHwPortalConfigTypeService selectHwPortalConfigTypeList public List<HwPortalConfigType> HwPortalConfigType hwPortalConfigType src/main/java/com/ruoyi/portal/service/IHwPortalConfigTypeService.java
IHwPortalConfigTypeService selectPortalConfigTypeTreeList public List<TreeSelect> HwPortalConfigType portalConfigType src/main/java/com/ruoyi/portal/service/IHwPortalConfigTypeService.java
IHwPortalConfigTypeService updateHwPortalConfigType public int HwPortalConfigType hwPortalConfigType src/main/java/com/ruoyi/portal/service/IHwPortalConfigTypeService.java
IHwProductCaseInfoService deleteHwProductCaseInfoByCaseInfoId public int Long caseInfoId src/main/java/com/ruoyi/portal/service/IHwProductCaseInfoService.java
IHwProductCaseInfoService deleteHwProductCaseInfoByCaseInfoIds public int Long[] caseInfoIds src/main/java/com/ruoyi/portal/service/IHwProductCaseInfoService.java
IHwProductCaseInfoService getTypicalHomeCaseInfo public HwProductCaseInfo HwProductCaseInfo hwProductCaseInfo src/main/java/com/ruoyi/portal/service/IHwProductCaseInfoService.java
IHwProductCaseInfoService insertHwProductCaseInfo public int HwProductCaseInfo hwProductCaseInfo src/main/java/com/ruoyi/portal/service/IHwProductCaseInfoService.java
IHwProductCaseInfoService selectHwProductCaseInfoByCaseInfoId public HwProductCaseInfo Long caseInfoId src/main/java/com/ruoyi/portal/service/IHwProductCaseInfoService.java
IHwProductCaseInfoService selectHwProductCaseInfoJoinList public List<HwProductCaseInfo> HwProductCaseInfo hwProductCaseInfo src/main/java/com/ruoyi/portal/service/IHwProductCaseInfoService.java
IHwProductCaseInfoService selectHwProductCaseInfoList public List<HwProductCaseInfo> HwProductCaseInfo hwProductCaseInfo src/main/java/com/ruoyi/portal/service/IHwProductCaseInfoService.java
IHwProductCaseInfoService updateHwProductCaseInfo public int HwProductCaseInfo hwProductCaseInfo src/main/java/com/ruoyi/portal/service/IHwProductCaseInfoService.java
IHwProductInfoDetailService deleteHwProductInfoDetailByProductInfoDetailId public int Long productInfoDetailId src/main/java/com/ruoyi/portal/service/IHwProductInfoDetailService.java
IHwProductInfoDetailService deleteHwProductInfoDetailByProductInfoDetailIds public int Long[] productInfoDetailIds src/main/java/com/ruoyi/portal/service/IHwProductInfoDetailService.java
IHwProductInfoDetailService insertHwProductInfoDetail public int HwProductInfoDetail hwProductInfoDetail src/main/java/com/ruoyi/portal/service/IHwProductInfoDetailService.java
IHwProductInfoDetailService selectHwProductInfoDetailByProductInfoDetailId public HwProductInfoDetail Long productInfoDetailId src/main/java/com/ruoyi/portal/service/IHwProductInfoDetailService.java
IHwProductInfoDetailService selectHwProductInfoDetailList public List<HwProductInfoDetail> HwProductInfoDetail hwProductInfoDetail src/main/java/com/ruoyi/portal/service/IHwProductInfoDetailService.java
IHwProductInfoDetailService updateHwProductInfoDetail public int HwProductInfoDetail hwProductInfoDetail src/main/java/com/ruoyi/portal/service/IHwProductInfoDetailService.java
IHwProductInfoService deleteHwProductInfoByProductInfoId public int Long productInfoId src/main/java/com/ruoyi/portal/service/IHwProductInfoService.java
IHwProductInfoService deleteHwProductInfoByProductInfoIds public int Long[] productInfoIds src/main/java/com/ruoyi/portal/service/IHwProductInfoService.java
IHwProductInfoService insertHwProductInfo public int HwProductInfo hwProductInfo src/main/java/com/ruoyi/portal/service/IHwProductInfoService.java
IHwProductInfoService selectHwProductInfoByProductInfoId public HwProductInfo Long productInfoId src/main/java/com/ruoyi/portal/service/IHwProductInfoService.java
IHwProductInfoService selectHwProductInfoJoinDetailList public List<HwProductInfo> HwProductInfo hwProductInfo src/main/java/com/ruoyi/portal/service/IHwProductInfoService.java
IHwProductInfoService selectHwProductInfoJoinList public List<HwProductInfo> HwProductInfo hwProductInfo src/main/java/com/ruoyi/portal/service/IHwProductInfoService.java
IHwProductInfoService selectHwProductInfoList public List<HwProductInfo> HwProductInfo hwProductInfo src/main/java/com/ruoyi/portal/service/IHwProductInfoService.java
IHwProductInfoService updateHwProductInfo public int HwProductInfo hwProductInfo src/main/java/com/ruoyi/portal/service/IHwProductInfoService.java
IHwSearchRebuildService rebuildAll void `` src/main/java/com/ruoyi/portal/service/IHwSearchRebuildService.java
IHwSearchService search SearchPageDTO String keyword, Integer pageNum, Integer pageSize src/main/java/com/ruoyi/portal/service/IHwSearchService.java
IHwSearchService searchForEdit SearchPageDTO String keyword, Integer pageNum, Integer pageSize src/main/java/com/ruoyi/portal/service/IHwSearchService.java
IHwWebDocumentService deleteHwWebDocumentByDocumentId public int String documentId src/main/java/com/ruoyi/portal/service/IHwWebDocumentService.java
IHwWebDocumentService deleteHwWebDocumentByDocumentIds public int String[] documentIds src/main/java/com/ruoyi/portal/service/IHwWebDocumentService.java
IHwWebDocumentService insertHwWebDocument public int HwWebDocument hwWebDocument src/main/java/com/ruoyi/portal/service/IHwWebDocumentService.java
IHwWebDocumentService selectHwWebDocumentByDocumentId public HwWebDocument String documentId src/main/java/com/ruoyi/portal/service/IHwWebDocumentService.java
IHwWebDocumentService selectHwWebDocumentList public List<HwWebDocument> HwWebDocument hwWebDocument src/main/java/com/ruoyi/portal/service/IHwWebDocumentService.java
IHwWebDocumentService updateHwWebDocument public int HwWebDocument hwWebDocument src/main/java/com/ruoyi/portal/service/IHwWebDocumentService.java
IHwWebMenuService deleteHwWebMenuByWebMenuId public int Long webMenuId src/main/java/com/ruoyi/portal/service/IHwWebMenuService.java
IHwWebMenuService deleteHwWebMenuByWebMenuIds public int Long[] webMenuIds src/main/java/com/ruoyi/portal/service/IHwWebMenuService.java
IHwWebMenuService insertHwWebMenu public int HwWebMenu hwWebMenu src/main/java/com/ruoyi/portal/service/IHwWebMenuService.java
IHwWebMenuService selectHwWebMenuByWebMenuId public HwWebMenu Long webMenuId src/main/java/com/ruoyi/portal/service/IHwWebMenuService.java
IHwWebMenuService selectHwWebMenuList public List<HwWebMenu> HwWebMenu hwWebMenu src/main/java/com/ruoyi/portal/service/IHwWebMenuService.java
IHwWebMenuService selectMenuTree public List<HwWebMenu> HwWebMenu hwWebMenu src/main/java/com/ruoyi/portal/service/IHwWebMenuService.java
IHwWebMenuService updateHwWebMenu public int HwWebMenu hwWebMenu src/main/java/com/ruoyi/portal/service/IHwWebMenuService.java
IHwWebMenuService1 deleteHwWebMenuByWebMenuId public int Long webMenuId src/main/java/com/ruoyi/portal/service/IHwWebMenuService1.java
IHwWebMenuService1 deleteHwWebMenuByWebMenuIds public int Long[] webMenuIds src/main/java/com/ruoyi/portal/service/IHwWebMenuService1.java
IHwWebMenuService1 insertHwWebMenu public int HwWebMenu1 HwWebMenu1 src/main/java/com/ruoyi/portal/service/IHwWebMenuService1.java
IHwWebMenuService1 selectHwWebMenuByWebMenuId public HwWebMenu1 Long webMenuId src/main/java/com/ruoyi/portal/service/IHwWebMenuService1.java
IHwWebMenuService1 selectHwWebMenuList public List<HwWebMenu1> HwWebMenu1 HwWebMenu1 src/main/java/com/ruoyi/portal/service/IHwWebMenuService1.java
IHwWebMenuService1 selectMenuTree public List<HwWebMenu1> HwWebMenu1 HwWebMenu1 src/main/java/com/ruoyi/portal/service/IHwWebMenuService1.java
IHwWebMenuService1 updateHwWebMenu public int HwWebMenu1 HwWebMenu1 src/main/java/com/ruoyi/portal/service/IHwWebMenuService1.java
IHwWebService deleteHwWebByWebId public int Long webId src/main/java/com/ruoyi/portal/service/IHwWebService.java
IHwWebService deleteHwWebByWebIds public int Long[] webIds src/main/java/com/ruoyi/portal/service/IHwWebService.java
IHwWebService insertHwWeb public int HwWeb hwWeb src/main/java/com/ruoyi/portal/service/IHwWebService.java
IHwWebService selectHwWebByWebcode public HwWeb Long webCode src/main/java/com/ruoyi/portal/service/IHwWebService.java
IHwWebService selectHwWebList public List<HwWeb> HwWeb hwWeb src/main/java/com/ruoyi/portal/service/IHwWebService.java
IHwWebService updateHwWeb public int HwWeb hwWeb src/main/java/com/ruoyi/portal/service/IHwWebService.java
IHwWebService1 deleteHwWebByWebId public int Long webId src/main/java/com/ruoyi/portal/service/IHwWebService1.java
IHwWebService1 deleteHwWebByWebIds public int Long[] webIds src/main/java/com/ruoyi/portal/service/IHwWebService1.java
IHwWebService1 insertHwWeb public int HwWeb1 hwWeb1 src/main/java/com/ruoyi/portal/service/IHwWebService1.java
IHwWebService1 selectHwWebByWebcode public HwWeb1 Long webCode src/main/java/com/ruoyi/portal/service/IHwWebService1.java
IHwWebService1 selectHwWebList public List<HwWeb1> HwWeb1 hwWeb1 src/main/java/com/ruoyi/portal/service/IHwWebService1.java
IHwWebService1 selectHwWebOne public HwWeb1 HwWeb1 hwWeb1 src/main/java/com/ruoyi/portal/service/IHwWebService1.java
IHwWebService1 updateHwWeb public int HwWeb1 hwWeb1 src/main/java/com/ruoyi/portal/service/IHwWebService1.java
PortalSearchEsService search SearchPageDTO String keyword, Integer pageNum, Integer pageSize, boolean editMode src/main/java/com/ruoyi/portal/search/service/PortalSearchEsService.java

5.2 Mapper 接口

Mapper 方法 返回值 参数 源文件
HwAboutUsInfoDetailMapper deleteHwAboutUsInfoDetailByUsInfoDetailId public int Long usInfoDetailId src/main/java/com/ruoyi/portal/mapper/HwAboutUsInfoDetailMapper.java
HwAboutUsInfoDetailMapper deleteHwAboutUsInfoDetailByUsInfoDetailIds public int Long[] usInfoDetailIds src/main/java/com/ruoyi/portal/mapper/HwAboutUsInfoDetailMapper.java
HwAboutUsInfoDetailMapper insertHwAboutUsInfoDetail public int HwAboutUsInfoDetail hwAboutUsInfoDetail src/main/java/com/ruoyi/portal/mapper/HwAboutUsInfoDetailMapper.java
HwAboutUsInfoDetailMapper selectHwAboutUsInfoDetailByUsInfoDetailId public HwAboutUsInfoDetail Long usInfoDetailId src/main/java/com/ruoyi/portal/mapper/HwAboutUsInfoDetailMapper.java
HwAboutUsInfoDetailMapper selectHwAboutUsInfoDetailList public List<HwAboutUsInfoDetail> HwAboutUsInfoDetail hwAboutUsInfoDetail src/main/java/com/ruoyi/portal/mapper/HwAboutUsInfoDetailMapper.java
HwAboutUsInfoDetailMapper updateHwAboutUsInfoDetail public int HwAboutUsInfoDetail hwAboutUsInfoDetail src/main/java/com/ruoyi/portal/mapper/HwAboutUsInfoDetailMapper.java
HwAboutUsInfoMapper deleteHwAboutUsInfoByAboutUsInfoId public int Long aboutUsInfoId src/main/java/com/ruoyi/portal/mapper/HwAboutUsInfoMapper.java
HwAboutUsInfoMapper deleteHwAboutUsInfoByAboutUsInfoIds public int Long[] aboutUsInfoIds src/main/java/com/ruoyi/portal/mapper/HwAboutUsInfoMapper.java
HwAboutUsInfoMapper insertHwAboutUsInfo public int HwAboutUsInfo hwAboutUsInfo src/main/java/com/ruoyi/portal/mapper/HwAboutUsInfoMapper.java
HwAboutUsInfoMapper selectHwAboutUsInfoByAboutUsInfoId public HwAboutUsInfo Long aboutUsInfoId src/main/java/com/ruoyi/portal/mapper/HwAboutUsInfoMapper.java
HwAboutUsInfoMapper selectHwAboutUsInfoList public List<HwAboutUsInfo> HwAboutUsInfo hwAboutUsInfo src/main/java/com/ruoyi/portal/mapper/HwAboutUsInfoMapper.java
HwAboutUsInfoMapper updateHwAboutUsInfo public int HwAboutUsInfo hwAboutUsInfo src/main/java/com/ruoyi/portal/mapper/HwAboutUsInfoMapper.java
HwAnalyticsMapper avgStayMs Long @Param("statDate") LocalDate statDate src/main/java/com/ruoyi/portal/mapper/HwAnalyticsMapper.java
HwAnalyticsMapper countDistinctIp Long @Param("statDate") LocalDate statDate src/main/java/com/ruoyi/portal/mapper/HwAnalyticsMapper.java
HwAnalyticsMapper countDistinctSessions Long @Param("statDate") LocalDate statDate src/main/java/com/ruoyi/portal/mapper/HwAnalyticsMapper.java
HwAnalyticsMapper countDistinctVisitor Long @Param("statDate") LocalDate statDate src/main/java/com/ruoyi/portal/mapper/HwAnalyticsMapper.java
HwAnalyticsMapper countEventByType Long @Param("statDate") LocalDate statDate, @Param("eventType") String eventType src/main/java/com/ruoyi/portal/mapper/HwAnalyticsMapper.java
HwAnalyticsMapper countSinglePageSessions Long @Param("statDate") LocalDate statDate src/main/java/com/ruoyi/portal/mapper/HwAnalyticsMapper.java
HwAnalyticsMapper insertVisitEvent int HwWebVisitEvent event src/main/java/com/ruoyi/portal/mapper/HwAnalyticsMapper.java
HwAnalyticsMapper selectDailyByDate HwWebVisitDaily @Param("statDate") LocalDate statDate src/main/java/com/ruoyi/portal/mapper/HwAnalyticsMapper.java
HwAnalyticsMapper selectTopEntryPages List<AnalyticsRankItemDTO> @Param("statDate") LocalDate statDate, @Param("limit") int limit src/main/java/com/ruoyi/portal/mapper/HwAnalyticsMapper.java
HwAnalyticsMapper selectTopHotPages List<AnalyticsRankItemDTO> @Param("statDate") LocalDate statDate, @Param("limit") int limit src/main/java/com/ruoyi/portal/mapper/HwAnalyticsMapper.java
HwAnalyticsMapper selectTopKeywords List<AnalyticsRankItemDTO> @Param("statDate") LocalDate statDate, @Param("limit") int limit src/main/java/com/ruoyi/portal/mapper/HwAnalyticsMapper.java
HwAnalyticsMapper upsertDaily int HwWebVisitDaily daily src/main/java/com/ruoyi/portal/mapper/HwAnalyticsMapper.java
HwContactUsInfoMapper deleteHwContactUsInfoByContactUsInfoId public int Long contactUsInfoId src/main/java/com/ruoyi/portal/mapper/HwContactUsInfoMapper.java
HwContactUsInfoMapper deleteHwContactUsInfoByContactUsInfoIds public int Long[] contactUsInfoIds src/main/java/com/ruoyi/portal/mapper/HwContactUsInfoMapper.java
HwContactUsInfoMapper insertHwContactUsInfo public int HwContactUsInfo hwContactUsInfo src/main/java/com/ruoyi/portal/mapper/HwContactUsInfoMapper.java
HwContactUsInfoMapper selectHwContactUsInfoByContactUsInfoId public HwContactUsInfo Long contactUsInfoId src/main/java/com/ruoyi/portal/mapper/HwContactUsInfoMapper.java
HwContactUsInfoMapper selectHwContactUsInfoList public List<HwContactUsInfo> HwContactUsInfo hwContactUsInfo src/main/java/com/ruoyi/portal/mapper/HwContactUsInfoMapper.java
HwContactUsInfoMapper updateHwContactUsInfo public int HwContactUsInfo hwContactUsInfo src/main/java/com/ruoyi/portal/mapper/HwContactUsInfoMapper.java
HwPortalConfigMapper deleteHwPortalConfigByPortalConfigId public int Long portalConfigId src/main/java/com/ruoyi/portal/mapper/HwPortalConfigMapper.java
HwPortalConfigMapper deleteHwPortalConfigByPortalConfigIds public int Long[] portalConfigIds src/main/java/com/ruoyi/portal/mapper/HwPortalConfigMapper.java
HwPortalConfigMapper insertHwPortalConfig public int HwPortalConfig hwPortalConfig src/main/java/com/ruoyi/portal/mapper/HwPortalConfigMapper.java
HwPortalConfigMapper selectHwPortalConfigByPortalConfigId public HwPortalConfig Long portalConfigId src/main/java/com/ruoyi/portal/mapper/HwPortalConfigMapper.java
HwPortalConfigMapper selectHwPortalConfigJoinList public List<HwPortalConfig> HwPortalConfig hwPortalConfig src/main/java/com/ruoyi/portal/mapper/HwPortalConfigMapper.java
HwPortalConfigMapper selectHwPortalConfigList public List<HwPortalConfig> HwPortalConfig hwPortalConfig src/main/java/com/ruoyi/portal/mapper/HwPortalConfigMapper.java
HwPortalConfigMapper selectHwPortalConfigList2 public List<HwPortalConfig> HwPortalConfig hwPortalConfig src/main/java/com/ruoyi/portal/mapper/HwPortalConfigMapper.java
HwPortalConfigMapper updateHwPortalConfig public int HwPortalConfig hwPortalConfig src/main/java/com/ruoyi/portal/mapper/HwPortalConfigMapper.java
HwPortalConfigTypeMapper deleteHwPortalConfigTypeByConfigTypeId public int Long configTypeId src/main/java/com/ruoyi/portal/mapper/HwPortalConfigTypeMapper.java
HwPortalConfigTypeMapper deleteHwPortalConfigTypeByConfigTypeIds public int Long[] configTypeIds src/main/java/com/ruoyi/portal/mapper/HwPortalConfigTypeMapper.java
HwPortalConfigTypeMapper insertHwPortalConfigType public int HwPortalConfigType hwPortalConfigType src/main/java/com/ruoyi/portal/mapper/HwPortalConfigTypeMapper.java
HwPortalConfigTypeMapper selectHwPortalConfigTypeByConfigTypeId public HwPortalConfigType Long configTypeId src/main/java/com/ruoyi/portal/mapper/HwPortalConfigTypeMapper.java
HwPortalConfigTypeMapper selectHwPortalConfigTypeList public List<HwPortalConfigType> HwPortalConfigType hwPortalConfigType src/main/java/com/ruoyi/portal/mapper/HwPortalConfigTypeMapper.java
HwPortalConfigTypeMapper updateHwPortalConfigType public int HwPortalConfigType hwPortalConfigType src/main/java/com/ruoyi/portal/mapper/HwPortalConfigTypeMapper.java
HwProductCaseInfoMapper deleteHwProductCaseInfoByCaseInfoId public int Long caseInfoId src/main/java/com/ruoyi/portal/mapper/HwProductCaseInfoMapper.java
HwProductCaseInfoMapper deleteHwProductCaseInfoByCaseInfoIds public int Long[] caseInfoIds src/main/java/com/ruoyi/portal/mapper/HwProductCaseInfoMapper.java
HwProductCaseInfoMapper insertHwProductCaseInfo public int HwProductCaseInfo hwProductCaseInfo src/main/java/com/ruoyi/portal/mapper/HwProductCaseInfoMapper.java
HwProductCaseInfoMapper selectHwProductCaseInfoByCaseInfoId public HwProductCaseInfo Long caseInfoId src/main/java/com/ruoyi/portal/mapper/HwProductCaseInfoMapper.java
HwProductCaseInfoMapper selectHwProductCaseInfoJoinList public List<HwProductCaseInfo> HwProductCaseInfo hwProductCaseInfo src/main/java/com/ruoyi/portal/mapper/HwProductCaseInfoMapper.java
HwProductCaseInfoMapper selectHwProductCaseInfoList public List<HwProductCaseInfo> HwProductCaseInfo hwProductCaseInfo src/main/java/com/ruoyi/portal/mapper/HwProductCaseInfoMapper.java
HwProductCaseInfoMapper updateHwProductCaseInfo public int HwProductCaseInfo hwProductCaseInfo src/main/java/com/ruoyi/portal/mapper/HwProductCaseInfoMapper.java
HwProductInfoDetailMapper deleteHwProductInfoDetailByProductInfoDetailId public int Long productInfoDetailId src/main/java/com/ruoyi/portal/mapper/HwProductInfoDetailMapper.java
HwProductInfoDetailMapper deleteHwProductInfoDetailByProductInfoDetailIds public int Long[] productInfoDetailIds src/main/java/com/ruoyi/portal/mapper/HwProductInfoDetailMapper.java
HwProductInfoDetailMapper insertHwProductInfoDetail public int HwProductInfoDetail hwProductInfoDetail src/main/java/com/ruoyi/portal/mapper/HwProductInfoDetailMapper.java
HwProductInfoDetailMapper selectHwProductInfoDetailByProductInfoDetailId public HwProductInfoDetail Long productInfoDetailId src/main/java/com/ruoyi/portal/mapper/HwProductInfoDetailMapper.java
HwProductInfoDetailMapper selectHwProductInfoDetailList public List<HwProductInfoDetail> HwProductInfoDetail hwProductInfoDetail src/main/java/com/ruoyi/portal/mapper/HwProductInfoDetailMapper.java
HwProductInfoDetailMapper updateHwProductInfoDetail public int HwProductInfoDetail hwProductInfoDetail src/main/java/com/ruoyi/portal/mapper/HwProductInfoDetailMapper.java
HwProductInfoMapper deleteHwProductInfoByProductInfoId public int Long productInfoId src/main/java/com/ruoyi/portal/mapper/HwProductInfoMapper.java
HwProductInfoMapper deleteHwProductInfoByProductInfoIds public int Long[] productInfoIds src/main/java/com/ruoyi/portal/mapper/HwProductInfoMapper.java
HwProductInfoMapper insertHwProductInfo public int HwProductInfo hwProductInfo src/main/java/com/ruoyi/portal/mapper/HwProductInfoMapper.java
HwProductInfoMapper selectHwProductInfoByProductInfoId public HwProductInfo Long productInfoId src/main/java/com/ruoyi/portal/mapper/HwProductInfoMapper.java
HwProductInfoMapper selectHwProductInfoJoinDetailList public List<HwProductInfo> HwProductInfo hwProductInfo src/main/java/com/ruoyi/portal/mapper/HwProductInfoMapper.java
HwProductInfoMapper selectHwProductInfoJoinList public List<HwProductInfo> HwProductInfo hwProductInfo src/main/java/com/ruoyi/portal/mapper/HwProductInfoMapper.java
HwProductInfoMapper selectHwProductInfoList public List<HwProductInfo> HwProductInfo hwProductInfo src/main/java/com/ruoyi/portal/mapper/HwProductInfoMapper.java
HwProductInfoMapper updateHwProductInfo public int HwProductInfo hwProductInfo src/main/java/com/ruoyi/portal/mapper/HwProductInfoMapper.java
HwSearchMapper searchByKeyword List<SearchRawRecord> @Param("keyword") String keyword src/main/java/com/ruoyi/portal/mapper/HwSearchMapper.java
HwWebDocumentMapper deleteHwWebDocumentByDocumentId public int String documentId src/main/java/com/ruoyi/portal/mapper/HwWebDocumentMapper.java
HwWebDocumentMapper deleteHwWebDocumentByDocumentIds public int String[] documentIds src/main/java/com/ruoyi/portal/mapper/HwWebDocumentMapper.java
HwWebDocumentMapper insertHwWebDocument public int HwWebDocument hwWebDocument src/main/java/com/ruoyi/portal/mapper/HwWebDocumentMapper.java
HwWebDocumentMapper selectHwWebDocumentByDocumentId public HwWebDocument String documentId src/main/java/com/ruoyi/portal/mapper/HwWebDocumentMapper.java
HwWebDocumentMapper selectHwWebDocumentList public List<HwWebDocument> HwWebDocument hwWebDocument src/main/java/com/ruoyi/portal/mapper/HwWebDocumentMapper.java
HwWebDocumentMapper updateHwWebDocument public int HwWebDocument hwWebDocument src/main/java/com/ruoyi/portal/mapper/HwWebDocumentMapper.java
HwWebMapper deleteHwWebByWebId public int Long webId src/main/java/com/ruoyi/portal/mapper/HwWebMapper.java
HwWebMapper deleteHwWebByWebIds public int Long[] webIds src/main/java/com/ruoyi/portal/mapper/HwWebMapper.java
HwWebMapper insertHwWeb public int HwWeb hwWeb src/main/java/com/ruoyi/portal/mapper/HwWebMapper.java
HwWebMapper selectHwWebByWebcode public HwWeb Long webCode src/main/java/com/ruoyi/portal/mapper/HwWebMapper.java
HwWebMapper selectHwWebList public List<HwWeb> HwWeb hwWeb src/main/java/com/ruoyi/portal/mapper/HwWebMapper.java
HwWebMapper updateHwWeb public int HwWeb hwWeb src/main/java/com/ruoyi/portal/mapper/HwWebMapper.java
HwWebMapper1 deleteHwWebByWebId public int Long webId src/main/java/com/ruoyi/portal/mapper/HwWebMapper1.java
HwWebMapper1 deleteHwWebByWebIds public int Long[] webIds src/main/java/com/ruoyi/portal/mapper/HwWebMapper1.java
HwWebMapper1 insertHwWeb public int HwWeb1 hwWeb1 src/main/java/com/ruoyi/portal/mapper/HwWebMapper1.java
HwWebMapper1 selectHwWebByWebcode public HwWeb1 Long webCode src/main/java/com/ruoyi/portal/mapper/HwWebMapper1.java
HwWebMapper1 selectHwWebList public List<HwWeb1> HwWeb1 hwWeb1 src/main/java/com/ruoyi/portal/mapper/HwWebMapper1.java
HwWebMapper1 selectHwWebOne public HwWeb1 HwWeb1 hwWeb1 src/main/java/com/ruoyi/portal/mapper/HwWebMapper1.java
HwWebMapper1 updateHwWeb public int HwWeb1 hwWeb1 src/main/java/com/ruoyi/portal/mapper/HwWebMapper1.java
HwWebMenuMapper deleteHwWebMenuByWebMenuId public int Long webMenuId src/main/java/com/ruoyi/portal/mapper/HwWebMenuMapper.java
HwWebMenuMapper deleteHwWebMenuByWebMenuIds public int Long[] webMenuIds src/main/java/com/ruoyi/portal/mapper/HwWebMenuMapper.java
HwWebMenuMapper insertHwWebMenu public int HwWebMenu hwWebMenu src/main/java/com/ruoyi/portal/mapper/HwWebMenuMapper.java
HwWebMenuMapper selectHwWebMenuByWebMenuId public HwWebMenu Long webMenuId src/main/java/com/ruoyi/portal/mapper/HwWebMenuMapper.java
HwWebMenuMapper selectHwWebMenuList public List<HwWebMenu> HwWebMenu hwWebMenu src/main/java/com/ruoyi/portal/mapper/HwWebMenuMapper.java
HwWebMenuMapper updateHwWebMenu public int HwWebMenu hwWebMenu src/main/java/com/ruoyi/portal/mapper/HwWebMenuMapper.java
HwWebMenuMapper1 deleteHwWebMenuByWebMenuId public int Long webMenuId src/main/java/com/ruoyi/portal/mapper/HwWebMenuMapper1.java
HwWebMenuMapper1 deleteHwWebMenuByWebMenuIds public int Long[] webMenuIds src/main/java/com/ruoyi/portal/mapper/HwWebMenuMapper1.java
HwWebMenuMapper1 insertHwWebMenu public int HwWebMenu1 HwWebMenu1 src/main/java/com/ruoyi/portal/mapper/HwWebMenuMapper1.java
HwWebMenuMapper1 selectHwWebMenuByWebMenuId public HwWebMenu1 Long webMenuId src/main/java/com/ruoyi/portal/mapper/HwWebMenuMapper1.java
HwWebMenuMapper1 selectHwWebMenuList public List<HwWebMenu1> HwWebMenu1 HwWebMenu1 src/main/java/com/ruoyi/portal/mapper/HwWebMenuMapper1.java
HwWebMenuMapper1 selectMenuTree public List<HwWebMenu1> HwWebMenu1 hwWebMenu src/main/java/com/ruoyi/portal/mapper/HwWebMenuMapper1.java
HwWebMenuMapper1 updateHwWebMenu public int HwWebMenu1 HwWebMenu1 src/main/java/com/ruoyi/portal/mapper/HwWebMenuMapper1.java

5.3 MyBatis XML 操作

XML 操作 id 涉及表 源文件
HwAboutUsInfoDetailMapper.xml DELETE deleteHwAboutUsInfoDetailByUsInfoDetailId hw_about_us_info_detail src/main/resources/mapper/portal/HwAboutUsInfoDetailMapper.xml
HwAboutUsInfoDetailMapper.xml DELETE deleteHwAboutUsInfoDetailByUsInfoDetailIds hw_about_us_info_detail src/main/resources/mapper/portal/HwAboutUsInfoDetailMapper.xml
HwAboutUsInfoDetailMapper.xml INSERT insertHwAboutUsInfoDetail hw_about_us_info_detail src/main/resources/mapper/portal/HwAboutUsInfoDetailMapper.xml
HwAboutUsInfoDetailMapper.xml SELECT selectHwAboutUsInfoDetailByUsInfoDetailId hw_about_us_info_detail src/main/resources/mapper/portal/HwAboutUsInfoDetailMapper.xml
HwAboutUsInfoDetailMapper.xml SELECT selectHwAboutUsInfoDetailList hw_about_us_info_detail src/main/resources/mapper/portal/HwAboutUsInfoDetailMapper.xml
HwAboutUsInfoDetailMapper.xml UPDATE updateHwAboutUsInfoDetail hw_about_us_info_detail src/main/resources/mapper/portal/HwAboutUsInfoDetailMapper.xml
HwAboutUsInfoMapper.xml DELETE deleteHwAboutUsInfoByAboutUsInfoId hw_about_us_info src/main/resources/mapper/portal/HwAboutUsInfoMapper.xml
HwAboutUsInfoMapper.xml DELETE deleteHwAboutUsInfoByAboutUsInfoIds hw_about_us_info src/main/resources/mapper/portal/HwAboutUsInfoMapper.xml
HwAboutUsInfoMapper.xml INSERT insertHwAboutUsInfo hw_about_us_info src/main/resources/mapper/portal/HwAboutUsInfoMapper.xml
HwAboutUsInfoMapper.xml SELECT selectHwAboutUsInfoByAboutUsInfoId hw_about_us_info src/main/resources/mapper/portal/HwAboutUsInfoMapper.xml
HwAboutUsInfoMapper.xml SELECT selectHwAboutUsInfoList hw_about_us_info src/main/resources/mapper/portal/HwAboutUsInfoMapper.xml
HwAboutUsInfoMapper.xml UPDATE updateHwAboutUsInfo hw_about_us_info src/main/resources/mapper/portal/HwAboutUsInfoMapper.xml
HwAnalyticsMapper.xml INSERT insertVisitEvent hw_web_visit_event, hw_web_visit_daily src/main/resources/mapper/portal/HwAnalyticsMapper.xml
HwAnalyticsMapper.xml INSERT upsertDaily hw_web_visit_event, hw_web_visit_daily src/main/resources/mapper/portal/HwAnalyticsMapper.xml
HwAnalyticsMapper.xml SELECT avgStayMs hw_web_visit_event, hw_web_visit_daily src/main/resources/mapper/portal/HwAnalyticsMapper.xml
HwAnalyticsMapper.xml SELECT countDistinctIp hw_web_visit_event, hw_web_visit_daily src/main/resources/mapper/portal/HwAnalyticsMapper.xml
HwAnalyticsMapper.xml SELECT countDistinctSessions hw_web_visit_event, hw_web_visit_daily src/main/resources/mapper/portal/HwAnalyticsMapper.xml
HwAnalyticsMapper.xml SELECT countDistinctVisitor hw_web_visit_event, hw_web_visit_daily src/main/resources/mapper/portal/HwAnalyticsMapper.xml
HwAnalyticsMapper.xml SELECT countEventByType hw_web_visit_event, hw_web_visit_daily src/main/resources/mapper/portal/HwAnalyticsMapper.xml
HwAnalyticsMapper.xml SELECT countSinglePageSessions hw_web_visit_event, hw_web_visit_daily src/main/resources/mapper/portal/HwAnalyticsMapper.xml
HwAnalyticsMapper.xml SELECT selectDailyByDate hw_web_visit_event, hw_web_visit_daily src/main/resources/mapper/portal/HwAnalyticsMapper.xml
HwAnalyticsMapper.xml SELECT selectTopEntryPages hw_web_visit_event, hw_web_visit_daily src/main/resources/mapper/portal/HwAnalyticsMapper.xml
HwAnalyticsMapper.xml SELECT selectTopHotPages hw_web_visit_event, hw_web_visit_daily src/main/resources/mapper/portal/HwAnalyticsMapper.xml
HwAnalyticsMapper.xml SELECT selectTopKeywords hw_web_visit_event, hw_web_visit_daily src/main/resources/mapper/portal/HwAnalyticsMapper.xml
HwContactUsInfoMapper.xml DELETE deleteHwContactUsInfoByContactUsInfoId hw_contact_us_info src/main/resources/mapper/portal/HwContactUsInfoMapper.xml
HwContactUsInfoMapper.xml DELETE deleteHwContactUsInfoByContactUsInfoIds hw_contact_us_info src/main/resources/mapper/portal/HwContactUsInfoMapper.xml
HwContactUsInfoMapper.xml INSERT insertHwContactUsInfo hw_contact_us_info src/main/resources/mapper/portal/HwContactUsInfoMapper.xml
HwContactUsInfoMapper.xml SELECT selectHwContactUsInfoByContactUsInfoId hw_contact_us_info src/main/resources/mapper/portal/HwContactUsInfoMapper.xml
HwContactUsInfoMapper.xml SELECT selectHwContactUsInfoList hw_contact_us_info src/main/resources/mapper/portal/HwContactUsInfoMapper.xml
HwContactUsInfoMapper.xml UPDATE updateHwContactUsInfo hw_contact_us_info src/main/resources/mapper/portal/HwContactUsInfoMapper.xml
HwPortalConfigMapper.xml DELETE deleteHwPortalConfigByPortalConfigId hw_portal_config, hw_portal_config_type src/main/resources/mapper/portal/HwPortalConfigMapper.xml
HwPortalConfigMapper.xml DELETE deleteHwPortalConfigByPortalConfigIds hw_portal_config, hw_portal_config_type src/main/resources/mapper/portal/HwPortalConfigMapper.xml
HwPortalConfigMapper.xml INSERT insertHwPortalConfig hw_portal_config, hw_portal_config_type src/main/resources/mapper/portal/HwPortalConfigMapper.xml
HwPortalConfigMapper.xml SELECT selectHwPortalConfigByPortalConfigId hw_portal_config, hw_portal_config_type src/main/resources/mapper/portal/HwPortalConfigMapper.xml
HwPortalConfigMapper.xml SELECT selectHwPortalConfigJoinList hw_portal_config, hw_portal_config_type src/main/resources/mapper/portal/HwPortalConfigMapper.xml
HwPortalConfigMapper.xml SELECT selectHwPortalConfigList hw_portal_config, hw_portal_config_type src/main/resources/mapper/portal/HwPortalConfigMapper.xml
HwPortalConfigMapper.xml SELECT selectHwPortalConfigList2 hw_portal_config, hw_portal_config_type src/main/resources/mapper/portal/HwPortalConfigMapper.xml
HwPortalConfigMapper.xml UPDATE updateHwPortalConfig hw_portal_config, hw_portal_config_type src/main/resources/mapper/portal/HwPortalConfigMapper.xml
HwPortalConfigTypeMapper.xml DELETE deleteHwPortalConfigTypeByConfigTypeId hw_portal_config_type src/main/resources/mapper/portal/HwPortalConfigTypeMapper.xml
HwPortalConfigTypeMapper.xml DELETE deleteHwPortalConfigTypeByConfigTypeIds hw_portal_config_type src/main/resources/mapper/portal/HwPortalConfigTypeMapper.xml
HwPortalConfigTypeMapper.xml INSERT insertHwPortalConfigType hw_portal_config_type src/main/resources/mapper/portal/HwPortalConfigTypeMapper.xml
HwPortalConfigTypeMapper.xml SELECT selectHwPortalConfigTypeByConfigTypeId hw_portal_config_type src/main/resources/mapper/portal/HwPortalConfigTypeMapper.xml
HwPortalConfigTypeMapper.xml SELECT selectHwPortalConfigTypeList hw_portal_config_type src/main/resources/mapper/portal/HwPortalConfigTypeMapper.xml
HwPortalConfigTypeMapper.xml UPDATE updateHwPortalConfigType hw_portal_config_type src/main/resources/mapper/portal/HwPortalConfigTypeMapper.xml
HwProductCaseInfoMapper.xml DELETE deleteHwProductCaseInfoByCaseInfoId hw_product_case_info, hw_portal_config_type src/main/resources/mapper/portal/HwProductCaseInfoMapper.xml
HwProductCaseInfoMapper.xml DELETE deleteHwProductCaseInfoByCaseInfoIds hw_product_case_info, hw_portal_config_type src/main/resources/mapper/portal/HwProductCaseInfoMapper.xml
HwProductCaseInfoMapper.xml INSERT insertHwProductCaseInfo hw_product_case_info, hw_portal_config_type src/main/resources/mapper/portal/HwProductCaseInfoMapper.xml
HwProductCaseInfoMapper.xml SELECT selectHwProductCaseInfoByCaseInfoId hw_product_case_info, hw_portal_config_type src/main/resources/mapper/portal/HwProductCaseInfoMapper.xml
HwProductCaseInfoMapper.xml SELECT selectHwProductCaseInfoJoinList hw_product_case_info, hw_portal_config_type src/main/resources/mapper/portal/HwProductCaseInfoMapper.xml
HwProductCaseInfoMapper.xml SELECT selectHwProductCaseInfoList hw_product_case_info, hw_portal_config_type src/main/resources/mapper/portal/HwProductCaseInfoMapper.xml
HwProductCaseInfoMapper.xml UPDATE updateHwProductCaseInfo hw_product_case_info, hw_portal_config_type src/main/resources/mapper/portal/HwProductCaseInfoMapper.xml
HwProductInfoDetailMapper.xml DELETE deleteHwProductInfoDetailByProductInfoDetailId hw_product_info_detail src/main/resources/mapper/portal/HwProductInfoDetailMapper.xml
HwProductInfoDetailMapper.xml DELETE deleteHwProductInfoDetailByProductInfoDetailIds hw_product_info_detail src/main/resources/mapper/portal/HwProductInfoDetailMapper.xml
HwProductInfoDetailMapper.xml INSERT insertHwProductInfoDetail hw_product_info_detail src/main/resources/mapper/portal/HwProductInfoDetailMapper.xml
HwProductInfoDetailMapper.xml SELECT selectHwProductInfoDetailByProductInfoDetailId hw_product_info_detail src/main/resources/mapper/portal/HwProductInfoDetailMapper.xml
HwProductInfoDetailMapper.xml SELECT selectHwProductInfoDetailList hw_product_info_detail src/main/resources/mapper/portal/HwProductInfoDetailMapper.xml
HwProductInfoDetailMapper.xml UPDATE updateHwProductInfoDetail hw_product_info_detail src/main/resources/mapper/portal/HwProductInfoDetailMapper.xml
HwProductInfoMapper.xml DELETE deleteHwProductInfoByProductInfoId hw_product_info, hw_product_info_detail, hw_portal_config_type src/main/resources/mapper/portal/HwProductInfoMapper.xml
HwProductInfoMapper.xml DELETE deleteHwProductInfoByProductInfoIds hw_product_info, hw_product_info_detail, hw_portal_config_type src/main/resources/mapper/portal/HwProductInfoMapper.xml
HwProductInfoMapper.xml INSERT insertHwProductInfo hw_product_info, hw_product_info_detail, hw_portal_config_type src/main/resources/mapper/portal/HwProductInfoMapper.xml
HwProductInfoMapper.xml SELECT selectHwProductInfoByProductInfoId hw_product_info, hw_product_info_detail, hw_portal_config_type src/main/resources/mapper/portal/HwProductInfoMapper.xml
HwProductInfoMapper.xml SELECT selectHwProductInfoJoinDetailList hw_product_info, hw_product_info_detail, hw_portal_config_type src/main/resources/mapper/portal/HwProductInfoMapper.xml
HwProductInfoMapper.xml SELECT selectHwProductInfoJoinList hw_product_info, hw_product_info_detail, hw_portal_config_type src/main/resources/mapper/portal/HwProductInfoMapper.xml
HwProductInfoMapper.xml SELECT selectHwProductInfoList hw_product_info, hw_product_info_detail, hw_portal_config_type src/main/resources/mapper/portal/HwProductInfoMapper.xml
HwProductInfoMapper.xml UPDATE updateHwProductInfo hw_product_info, hw_product_info_detail, hw_portal_config_type src/main/resources/mapper/portal/HwProductInfoMapper.xml
HwSearchMapper.xml SELECT searchByKeyword hw_web_menu, hw_web, hw_web1, hw_web_document, hw_portal_config_type src/main/resources/mapper/portal/HwSearchMapper.xml
HwWebDocumentMapper.xml INSERT insertHwWebDocument hw_web_document src/main/resources/mapper/portal/HwWebDocumentMapper.xml
HwWebDocumentMapper.xml SELECT selectHwWebDocumentByDocumentId hw_web_document src/main/resources/mapper/portal/HwWebDocumentMapper.xml
HwWebDocumentMapper.xml SELECT selectHwWebDocumentList hw_web_document src/main/resources/mapper/portal/HwWebDocumentMapper.xml
HwWebDocumentMapper.xml UPDATE deleteHwWebDocumentByDocumentId hw_web_document src/main/resources/mapper/portal/HwWebDocumentMapper.xml
HwWebDocumentMapper.xml UPDATE deleteHwWebDocumentByDocumentIds hw_web_document src/main/resources/mapper/portal/HwWebDocumentMapper.xml
HwWebDocumentMapper.xml UPDATE updateHwWebDocument hw_web_document src/main/resources/mapper/portal/HwWebDocumentMapper.xml
HwWebMapper.xml INSERT insertHwWeb hw_web src/main/resources/mapper/portal/HwWebMapper.xml
HwWebMapper.xml SELECT selectHwWebByWebcode hw_web src/main/resources/mapper/portal/HwWebMapper.xml
HwWebMapper.xml SELECT selectHwWebList hw_web src/main/resources/mapper/portal/HwWebMapper.xml
HwWebMapper.xml UPDATE deleteHwWebByWebId hw_web src/main/resources/mapper/portal/HwWebMapper.xml
HwWebMapper.xml UPDATE deleteHwWebByWebIds hw_web src/main/resources/mapper/portal/HwWebMapper.xml
HwWebMapper.xml UPDATE updateHwWeb hw_web src/main/resources/mapper/portal/HwWebMapper.xml
HwWebMapper1.xml INSERT insertHwWeb hw_web1 src/main/resources/mapper/portal/HwWebMapper1.xml
HwWebMapper1.xml SELECT selectHwWebByWebcode hw_web1 src/main/resources/mapper/portal/HwWebMapper1.xml
HwWebMapper1.xml SELECT selectHwWebList hw_web1 src/main/resources/mapper/portal/HwWebMapper1.xml
HwWebMapper1.xml SELECT selectHwWebOne hw_web1 src/main/resources/mapper/portal/HwWebMapper1.xml
HwWebMapper1.xml UPDATE deleteHwWebByWebId hw_web1 src/main/resources/mapper/portal/HwWebMapper1.xml
HwWebMapper1.xml UPDATE deleteHwWebByWebIds hw_web1 src/main/resources/mapper/portal/HwWebMapper1.xml
HwWebMapper1.xml UPDATE updateHwWeb hw_web1 src/main/resources/mapper/portal/HwWebMapper1.xml
HwWebMenuMapper.xml INSERT insertHwWebMenu hw_web_menu src/main/resources/mapper/portal/HwWebMenuMapper.xml
HwWebMenuMapper.xml SELECT selectHwWebMenuByWebMenuId hw_web_menu src/main/resources/mapper/portal/HwWebMenuMapper.xml
HwWebMenuMapper.xml SELECT selectHwWebMenuList hw_web_menu src/main/resources/mapper/portal/HwWebMenuMapper.xml
HwWebMenuMapper.xml UPDATE deleteHwWebMenuByWebMenuId hw_web_menu src/main/resources/mapper/portal/HwWebMenuMapper.xml
HwWebMenuMapper.xml UPDATE deleteHwWebMenuByWebMenuIds hw_web_menu src/main/resources/mapper/portal/HwWebMenuMapper.xml
HwWebMenuMapper.xml UPDATE updateHwWebMenu hw_web_menu src/main/resources/mapper/portal/HwWebMenuMapper.xml
HwWebMenuMapper1.xml INSERT insertHwWebMenu hw_web_menu1 src/main/resources/mapper/portal/HwWebMenuMapper1.xml
HwWebMenuMapper1.xml SELECT selectHwWebMenuByWebMenuId hw_web_menu1 src/main/resources/mapper/portal/HwWebMenuMapper1.xml
HwWebMenuMapper1.xml SELECT selectHwWebMenuList hw_web_menu1 src/main/resources/mapper/portal/HwWebMenuMapper1.xml
HwWebMenuMapper1.xml UPDATE deleteHwWebMenuByWebMenuId hw_web_menu1 src/main/resources/mapper/portal/HwWebMenuMapper1.xml
HwWebMenuMapper1.xml UPDATE deleteHwWebMenuByWebMenuIds hw_web_menu1 src/main/resources/mapper/portal/HwWebMenuMapper1.xml
HwWebMenuMapper1.xml UPDATE updateHwWebMenu hw_web_menu1 src/main/resources/mapper/portal/HwWebMenuMapper1.xml

5.4 实体 / DTO / VO / 搜索文档清单

类型 源文件 直接依赖的 ruoyi-common 能力
AnalyticsCollectRequest src/main/java/com/ruoyi/portal/domain/dto/AnalyticsCollectRequest.java -
AnalyticsDashboardDTO src/main/java/com/ruoyi/portal/domain/dto/AnalyticsDashboardDTO.java -
AnalyticsRankItemDTO src/main/java/com/ruoyi/portal/domain/dto/AnalyticsRankItemDTO.java -
HwAboutUsInfo src/main/java/com/ruoyi/portal/domain/HwAboutUsInfo.java Excel, BaseEntity
HwAboutUsInfoDetail src/main/java/com/ruoyi/portal/domain/HwAboutUsInfoDetail.java Excel, BaseEntity
HwContactUsInfo src/main/java/com/ruoyi/portal/domain/HwContactUsInfo.java Excel, BaseEntity
HwPortalConfig src/main/java/com/ruoyi/portal/domain/HwPortalConfig.java Excel, BaseEntity
HwPortalConfigType src/main/java/com/ruoyi/portal/domain/HwPortalConfigType.java Excel, BaseEntity, TreeEntity
HwProductCaseInfo src/main/java/com/ruoyi/portal/domain/HwProductCaseInfo.java Excel, BaseEntity
HwProductInfo src/main/java/com/ruoyi/portal/domain/HwProductInfo.java Excel, BaseEntity
HwProductInfoDetail src/main/java/com/ruoyi/portal/domain/HwProductInfoDetail.java Excel, TreeEntity
HwWeb src/main/java/com/ruoyi/portal/domain/HwWeb.java Excel, BaseEntity
HwWeb1 src/main/java/com/ruoyi/portal/domain/HwWeb1.java Excel, BaseEntity
HwWebDocument src/main/java/com/ruoyi/portal/domain/HwWebDocument.java Excel, BaseEntity
HwWebMenu src/main/java/com/ruoyi/portal/domain/HwWebMenu.java Excel, TreeEntity
HwWebMenu1 src/main/java/com/ruoyi/portal/domain/HwWebMenu1.java Excel, TreeEntity
HwWebVisitDaily src/main/java/com/ruoyi/portal/domain/HwWebVisitDaily.java -
HwWebVisitEvent src/main/java/com/ruoyi/portal/domain/HwWebVisitEvent.java BaseEntity
PortalSearchDoc src/main/java/com/ruoyi/portal/search/es/entity/PortalSearchDoc.java -
SearchPageDTO src/main/java/com/ruoyi/portal/domain/dto/SearchPageDTO.java -
SearchRawRecord src/main/java/com/ruoyi/portal/domain/dto/SearchRawRecord.java -
SearchResultDTO src/main/java/com/ruoyi/portal/domain/dto/SearchResultDTO.java -
SecureDocumentRequest src/main/java/com/ruoyi/portal/domain/SecureDocumentRequest.java -
TreeSelect src/main/java/com/ruoyi/portal/domain/vo/TreeSelect.java -

6. 关键代码逻辑

6.1 HwAnalyticsServiceImpl.java

  • 埋点事件白名单固定为 page_view/page_leave/search_submit/download_click/contact_submit
  • IP 不直接存库,而是用 SHA-256(ip + "|hw-portal-analytics") 计算哈希;这个固定盐值必须保持不变,否则历史统计口径会断裂。
  • collect 每落一条事件就立即刷新当天汇总表。
  • refreshDailyStat 的跳出率算法是 singlePageSessionCount * 100 / sessionCount,并四舍五入到两位小数。

6.2 HwPortalConfigServiceImpl.java

  • selectHwPortalConfigList 根据 portalConfigType == "2" 在两套 SQL 之间切换:普通列表 SQL 与 selectHwPortalConfigList2
  • 这类“按字段切换 SQL 模板”的行为必须保留,不要在 C# 中合并成单条动态拼装 SQL。

6.3 HwPortalConfigTypeServiceImpl.java

  • selectConfigTypeList 在带 configTypeClassfication 过滤时,先查全量、再补齐所有子孙节点、最后组树;这不是普通 where 过滤。
  • insertHwPortalConfigType 会根据父节点补 parentId/ancestors/createTime/createBy,新增逻辑不能只做简单 Insert。
  • 树构造规则是“父节点为空、0、或父节点不在当前集合中即视为根”。

6.4 HwPortalController.java

  • 这是门户前台聚合控制器,不自己落库,只组合 config/configType/product/case/contact/aboutUs 多个服务。
  • 其中 getPortalConfigListgetHomeCaseTitleList 调用了 startPage();迁移到 Admin.NET 时如果要保持返回契约,需要保留分页行为而不是直接返回全部。
  • addContactUsInfo 会在入库前写入客户端 IP属于方法逻辑的一部分不能省略。

6.5 HwProductCaseInfoServiceImpl.java

  • getTypicalHomeCaseInfo 会先强制设置 homeTypicalFlag=1,再查询列表,然后优先返回 typicalFlag==1 的首条,否则回退到列表首条。
  • 没有命中数据时返回的是新的空对象,不是 null

6.6 HwProductInfoDetailServiceImpl.java

  • insertHwProductInfoDetail 会根据父节点补 parentId/ancestors/createTime/createBy
  • 这里 parentId == nullparentId == 0 都被归一成根节点,迁移时要保持相同行为。

6.7 HwProductInfoServiceImpl.java

  • selectHwProductInfoJoinDetailList 先跑 join SQL再在内存中按 configModal == 13 或明细 configModel == 13 把明细列表转换为树。
  • 树化后同时写入 TreeEntity.childrenhwProductInfoDetailList,前端可能依赖两套字段。

6.8 HwSearchMapper.xml

  • MySQL 搜索 SQL 由 5 段 UNION ALL 组成,只覆盖 menu/web/web1/document/configType
  • 每段都带固定基础分值menu=110、web1=90、web=80、document=70、configType=65随后服务层再叠加标题/内容命中分。

6.9 HwSearchRebuildServiceImpl.java

  • 索引名固定为 hw_portal_content。重建流程是:存在则删索引 -> 创建索引 -> 收集文档 -> 批量写入。
  • 当前仅重建 menu/web/web1/document/configType 五类文档,没有把 product/case/aboutUs 纳入 ES。

6.10 HwSearchServiceImpl.java

  • 搜索引擎选择规则是:search.es.enabled=truesearch.engine=es 且 ES 服务存在时优先走 ES任一条件不满足或 ES 异常时回退 MySQL。
  • MySQL 搜索先跑 HwSearchMapper.searchByKeyword,再在内存中做二次过滤、打分、摘要截取、高亮、分页。
  • 搜索关键字限制长度 50页大小上限 50MySQL SQL 内部结果上限 500。

6.11 HwWebDocumentController.java

  • 列表和详情接口都会把 secretKey 置空;当 hasSecret=true 时还会把 documentAddress 置空。
  • getSecureDocumentAddress 捕获异常后直接把错误信息返回前端,这也是现有接口契约的一部分。

6.12 HwWebDocumentServiceImpl.java

  • updateHwWebDocumentsecretKey == null 做了特殊归一:改成空字符串,以便触发 Mapper 更新逻辑清空数据库密钥。
  • verifyAndGetDocumentAddress 的判定规则是:数据库密钥为空则直接放行;否则要求前端传入去空格后的完全相等密钥。
  • 增删改成功后会静默重建搜索索引。

6.13 HwWebMenuServiceImpl.java

  • 菜单列表的树化发生在服务层,不在 SQL 里。
  • 增删改成功后会静默触发搜索索引重建,失败只记日志不回滚主业务。

6.14 HwWebMenuServiceImpl1.java

  • HwWebMenu1 是另一套菜单模型,保留了同样的树化规则,但没有搜索索引重建逻辑。

6.15 HwWebServiceImpl.java

  • updateHwWeb 不是更新原记录,而是按 webCode 查重后逻辑删除旧记录,再插入一条新记录。
  • 新插入前显式设置 isDelete = "0",并且整个过程包在事务里。

6.16 HwWebServiceImpl1.java

  • updateHwWeb 的唯一键是 webCode + typeId + deviceId,处理方式同 HwWebServiceImpl:先逻辑删除旧记录,再插入新记录。

6.17 PortalSearchDocConverter.java

  • web/web1 的 JSON 内容会先去 HTML再按 JSON 递归提取可搜索文本,并跳过 icon/url/banner/img/secretKey 等字段。
  • 路由和路由参数是在建索引阶段就写进文档,不是在查询阶段临时拼装。

7. ruoyi-common / Spring 能力替换为 Admin.NET 的映射

源能力 Admin.NET 建议替代
BaseController.startPage()/getDataTable() SqlSugarPagedList<T> 或自定义分页 DTO分页参数建议继承 BasePageInput
AjaxResult/success/error/toAjax AdminResultProvider 统一返回;业务层直接返回对象/分页对象,异常用 Oops.Oh(...) 或统一异常
@Anonymous Admin.NET 的 [AllowAnonymous]
@RepeatSubmit Admin.NET 的 [Idempotent],默认基于分布式锁与缓存去重
@RateLimiter 当前项目已启用 AspNetCoreRateLimit;若要保持按接口/IP 限流,需要在中间件策略或自定义特性中落地
DateUtils.getNowDate() .NETDateTime.Now 或统一时间工具,但要保持本地时区语义
SecurityUtils.getUsername() UserManager.Account / UserManager.RealName 视原字段含义选择
IpUtils.getIpAddr() HttpContext.GetRemoteIpAddressToIPv4(true)
UserAgentUtils.getBrowser()/getOperatingSystem() HttpContextExtension.GetClientBrowser()/GetClientOs() 或 UA Parser
StringUtils 优先用 string/string.IsNullOrWhiteSpace 与现有扩展;需要保留 defaultIfBlank/containsIgnoreCase 语义
MyBatis XML 若要求 SQL 文本完全不变,优先在 C# 仓库层用 ISqlSugarClient.Ado.SqlQueryAsync/ExecuteCommandAsync 执行原 SQL避免改写成 LINQ

7.1 当前模块对 com.ruoyi.common 的直接依赖分布

依赖 使用文件数
com.ruoyi.common.annotation.Anonymous 16
com.ruoyi.common.annotation.Excel 13
com.ruoyi.common.annotation.Log 16
com.ruoyi.common.annotation.RateLimiter 2
com.ruoyi.common.annotation.RepeatSubmit 14
com.ruoyi.common.constant.HwPortalConstants 1
com.ruoyi.common.constant.UserConstants 1
com.ruoyi.common.core.controller.BaseController 17
com.ruoyi.common.core.domain.AjaxResult 17
com.ruoyi.common.core.domain.BaseEntity 11
com.ruoyi.common.core.domain.TreeEntity 4
com.ruoyi.common.core.page.TableDataInfo 10
com.ruoyi.common.enums.BusinessType 16
com.ruoyi.common.enums.LimitType 2
com.ruoyi.common.exception.ServiceException 5
com.ruoyi.common.utils.DateUtils 9
com.ruoyi.common.utils.SecurityUtils 2
com.ruoyi.common.utils.StringUtils 8
com.ruoyi.common.utils.http.UserAgentUtils 1
com.ruoyi.common.utils.ip.IpUtils 2
com.ruoyi.common.utils.poi.ExcelUtil 13

8. 抽离到 hw-portal 的实施建议

8.1 分层建议

  1. Entity 层:按原表一比一建立 C# 实体,字段名、表名、主键、逻辑删除字段保持原样,避免任何列名重命名。
  2. Repository 层:每个 Java Mapper + XML 对应一个 C# Repository把 XML 中的 SQL 原样保存在 .sql 资源、常量字符串或独立类中,通过 ISqlSugarClient.Ado 执行。
  3. Service 层:严格按 Java ServiceImpl 的方法流程翻译,尤其是树构造、字段归一、软删再插入、索引静默重建、密钥校验、搜索打分与摘要。
  4. Api 层:如果要兼容原前端,优先保留原 URL、HTTP Method、入参与出参结构若统一为 Admin.NET 动态 API需要额外做路由别名或兼容层。

8.2 必须保持不变的“行为点”

  • 原 SQL 文本。
  • 原接口路径与 HTTP 方法。
  • HwWeb/HwWeb1 的“逻辑删旧记录再插入新记录”更新语义。
  • ancestors 的拼接规则。
  • 树根识别规则。
  • 搜索路由、路由参数、打分规则、摘要截断规则、高亮 HTML。
  • Analytics 的白名单事件、IP 哈希算法和固定盐值、日报刷新算法。
  • 文档密钥为空时直接放行、有密钥时精确匹配。

8.3 当前源码中需要特别留意的事实差异

  • SearchResultDTO 的注释声称会覆盖 productInfo/productDetail/caseInfo/aboutUs 等来源,但实际 MySQL 搜索 SQL 和 ES 重建只覆盖 menu/web/web1/document/configType。迁移时应以“实际代码行为”为准。
  • HwWebDocumentControllerHwPortalController 都标了匿名访问,这意味着迁移后要显式放开访问,而不是默认套用后台鉴权。
  • RepeatSubmit 在原系统大量使用,迁移后如果不补幂等控制,会出现行为退化。

9. 验证清单

  • 分别对 17 个 Controller 路由做契约对比,确认 URL、HTTP Method、参数名、空值行为、返回 JSON 结构一致。
  • 对 15 份 Mapper XML 的 SQL 做逐条对照,确认迁移后执行的 SQL 文本与原 XML 一致。
  • HwWeb/HwWeb1 更新接口做集成测试:旧记录应被逻辑删除,新记录新增成功。
  • 对配置类型树、菜单树、产品明细树做结构对比测试,确认 children 层级与根节点判定一致。
  • 对搜索做双通道验证MySQL 模式与 ES 模式都验证关键字命中、分页、高亮、编辑端路由。
  • 对 Analytics 做口径验证:collect -> daily 的 PV/UV/IP UV/停留时长/跳出率 与原算法一致。
  • 对文档密钥场景做安全验证:无密钥直接放行;有密钥时空字符串报错、错误密钥报错、正确密钥返回地址。

10. 附录:完整源码基线

以下附录直接贴出 ruoyi-portal 当前源码与 XML作为后续 hw-portal 抽离的原始对照基线。

ruoyi-portal/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>ruoyi</artifactId>
        <groupId>com.ruoyi</groupId>
        <version>3.9.1</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>ruoyi-portal</artifactId>

    <description>
        portal系统模块
    </description>

    <dependencies>

        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-common</artifactId>
        </dependency>

    </dependencies>

</project>

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwAboutUsInfoController.java

package com.ruoyi.portal.controller;

import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.portal.domain.HwAboutUsInfo;
import com.ruoyi.portal.service.IHwAboutUsInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;

/**
 * 关于我们信息Controller
 * 
 * @author xins
 * @date 2024-12-01
 */
@RestController
@Anonymous//不需要登陆任何人都可以操作
@RequestMapping("/portal/aboutUsInfo")
public class HwAboutUsInfoController extends BaseController
{
    @Autowired
    private IHwAboutUsInfoService hwAboutUsInfoService;

    /**
     * 查询关于我们信息列表
     */
    //@RequiresPermissions("portalaboutUsInfo:list")
    @GetMapping("/list")
    public TableDataInfo list(HwAboutUsInfo hwAboutUsInfo)
    {
        startPage();
        List<HwAboutUsInfo> list = hwAboutUsInfoService.selectHwAboutUsInfoList(hwAboutUsInfo);
        return getDataTable(list);
    }

    /**
     * 导出关于我们信息列表
     */
    //@RequiresPermissions("portalaboutUsInfo:export")
    //@Log(title = "关于我们信息", businessType = BusinessType.EXPORT)
    @RepeatSubmit
    @PostMapping("/export")
    public void export(HttpServletResponse response, HwAboutUsInfo hwAboutUsInfo)
    {
        List<HwAboutUsInfo> list = hwAboutUsInfoService.selectHwAboutUsInfoList(hwAboutUsInfo);
        ExcelUtil<HwAboutUsInfo> util = new ExcelUtil<HwAboutUsInfo>(HwAboutUsInfo.class);
        util.exportExcel(response, list, "关于我们信息数据");
    }

    /**
     * 获取关于我们信息详细信息
     */
    //@RequiresPermissions("portalaboutUsInfo:query")
    @GetMapping(value = "/{aboutUsInfoId}")
    public AjaxResult getInfo(@PathVariable("aboutUsInfoId") Long aboutUsInfoId)
    {
        return success(hwAboutUsInfoService.selectHwAboutUsInfoByAboutUsInfoId(aboutUsInfoId));
    }

    /**
     * 新增关于我们信息
     */
    //@RequiresPermissions("portalaboutUsInfo:add")
    //@Log(title = "关于我们信息", businessType = BusinessType.INSERT)
    @RepeatSubmit
    @PostMapping
    public AjaxResult add(@RequestBody HwAboutUsInfo hwAboutUsInfo)
    {
        return toAjax(hwAboutUsInfoService.insertHwAboutUsInfo(hwAboutUsInfo));
    }

    /**
     * 修改关于我们信息
     */
    //@RequiresPermissions("portalaboutUsInfo:edit")
    //@Log(title = "关于我们信息", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @PutMapping
    public AjaxResult edit(@RequestBody HwAboutUsInfo hwAboutUsInfo)
    {
        return toAjax(hwAboutUsInfoService.updateHwAboutUsInfo(hwAboutUsInfo));
    }

    /**
     * 删除关于我们信息
     */
    //@RequiresPermissions("portalaboutUsInfo:remove")
    //@Log(title = "关于我们信息", businessType = BusinessType.DELETE)
	@RepeatSubmit
	@DeleteMapping("/{aboutUsInfoIds}")
    public AjaxResult remove(@PathVariable Long[] aboutUsInfoIds)
    {
        return toAjax(hwAboutUsInfoService.deleteHwAboutUsInfoByAboutUsInfoIds(aboutUsInfoIds));
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwAboutUsInfoDetailController.java

package com.ruoyi.portal.controller;

import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.portal.domain.HwAboutUsInfoDetail;
import com.ruoyi.portal.service.IHwAboutUsInfoDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;

/**
 * 关于我们信息明细Controller
 * 
 * @author ruoyi
 * @date 2024-12-01
 */
@RestController
@RequestMapping("/portal/aboutUsInfoDetail")
@Anonymous//不需要登陆任何人都可以操作
public class HwAboutUsInfoDetailController extends BaseController
{
    @Autowired
    private IHwAboutUsInfoDetailService hwAboutUsInfoDetailService;

    /**
     * 查询关于我们信息明细列表
     */
    //@RequiresPermissions("portalaboutUsInfoDetail:list")
    @GetMapping("/list")
    public TableDataInfo list(HwAboutUsInfoDetail hwAboutUsInfoDetail)
    {
        startPage();
        List<HwAboutUsInfoDetail> list = hwAboutUsInfoDetailService.selectHwAboutUsInfoDetailList(hwAboutUsInfoDetail);
        return getDataTable(list);
    }

    /**
     * 导出关于我们信息明细列表
     */
    //@RequiresPermissions("portalaboutUsInfoDetail:export")
    //@Log(title = "关于我们信息明细", businessType = BusinessType.EXPORT)
    @RepeatSubmit
    @PostMapping("/export")
    public void export(HttpServletResponse response, HwAboutUsInfoDetail hwAboutUsInfoDetail)
    {
        List<HwAboutUsInfoDetail> list = hwAboutUsInfoDetailService.selectHwAboutUsInfoDetailList(hwAboutUsInfoDetail);
        ExcelUtil<HwAboutUsInfoDetail> util = new ExcelUtil<HwAboutUsInfoDetail>(HwAboutUsInfoDetail.class);
        util.exportExcel(response, list, "关于我们信息明细数据");
    }

    /**
     * 获取关于我们信息明细详细信息
     */
    //@RequiresPermissions("portalaboutUsInfoDetail:query")
    @GetMapping(value = "/{usInfoDetailId}")
    public AjaxResult getInfo(@PathVariable("usInfoDetailId") Long usInfoDetailId)
    {
        return success(hwAboutUsInfoDetailService.selectHwAboutUsInfoDetailByUsInfoDetailId(usInfoDetailId));
    }

    /**
     * 新增关于我们信息明细
     */
    //@RequiresPermissions("portalaboutUsInfoDetail:add")
    //@Log(title = "关于我们信息明细", businessType = BusinessType.INSERT)
    @RepeatSubmit
    @PostMapping
    public AjaxResult add(@RequestBody HwAboutUsInfoDetail hwAboutUsInfoDetail)
    {
        return toAjax(hwAboutUsInfoDetailService.insertHwAboutUsInfoDetail(hwAboutUsInfoDetail));
    }

    /**
     * 修改关于我们信息明细
     */
    //@RequiresPermissions("portalaboutUsInfoDetail:edit")
    //@Log(title = "关于我们信息明细", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @PutMapping
    public AjaxResult edit(@RequestBody HwAboutUsInfoDetail hwAboutUsInfoDetail)
    {
        return toAjax(hwAboutUsInfoDetailService.updateHwAboutUsInfoDetail(hwAboutUsInfoDetail));
    }

    /**
     * 删除关于我们信息明细
     */
    //@RequiresPermissions("portalaboutUsInfoDetail:remove")
    //@Log(title = "关于我们信息明细", businessType = BusinessType.DELETE)
	@RepeatSubmit
	@DeleteMapping("/{usInfoDetailIds}")
    public AjaxResult remove(@PathVariable Long[] usInfoDetailIds)
    {
        return toAjax(hwAboutUsInfoDetailService.deleteHwAboutUsInfoDetailByUsInfoDetailIds(usInfoDetailIds));
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwAnalyticsController.java

package com.ruoyi.portal.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RateLimiter;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.LimitType;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.portal.domain.dto.AnalyticsCollectRequest;
import com.ruoyi.portal.service.IHwAnalyticsService;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;

/**
 * 官网匿名访问监控
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/portal/analytics")
public class HwAnalyticsController extends BaseController
{
    private final IHwAnalyticsService hwAnalyticsService;

    private final ObjectMapper objectMapper = new ObjectMapper();

    public HwAnalyticsController(IHwAnalyticsService hwAnalyticsService)
    {
        this.hwAnalyticsService = hwAnalyticsService;
    }

    /**
     * 匿名访问事件采集
     */
    @Anonymous
    @RateLimiter(key = "portal_analytics_collect", time = 60, count = 240, limitType = LimitType.IP)
    @PostMapping(value = "/collect", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_PLAIN_VALUE})
    public AjaxResult collect(@RequestBody(required = false) String body, HttpServletRequest request)
    {
        if (body == null || body.trim().isEmpty())
        {
            return error("请求体不能为空");
        }
        try
        {
            AnalyticsCollectRequest collectRequest = objectMapper.readValue(body, AnalyticsCollectRequest.class);
            hwAnalyticsService.collect(collectRequest, IpUtils.getIpAddr(request), request.getHeader("User-Agent"));
            return success();
        }
        catch (Exception e)
        {
            return error("采集失败: " + e.getMessage());
        }
    }

    /**
     * 监控看板数据
     */
    @Log(title = "官网访问监控", businessType = BusinessType.OTHER)
    @GetMapping("/dashboard")
    public AjaxResult dashboard(@RequestParam(value = "statDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate statDate,
                                @RequestParam(value = "top", required = false) Integer top)
    {
        return success(hwAnalyticsService.getDashboard(statDate, top));
    }

    /**
     * 刷新某日统计数据
     */
    @Log(title = "官网访问监控", businessType = BusinessType.OTHER)
    @PostMapping("/refreshDaily")
    public AjaxResult refreshDaily(@RequestParam(value = "statDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate statDate)
    {
        hwAnalyticsService.refreshDailyStat(statDate);
        return success("刷新成功");
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwContactUsInfoController.java

package com.ruoyi.portal.controller;

import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.portal.domain.HwContactUsInfo;
import com.ruoyi.portal.service.IHwContactUsInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;

/**
 * 联系我们信息Controller
 * 
 * @author xins
 * @date 2024-12-01
 */
@RestController
@RequestMapping("/portal/contactUsInfo")
@Anonymous//不需要登陆任何人都可以操作
public class HwContactUsInfoController extends BaseController
{
    @Autowired
    private IHwContactUsInfoService hwContactUsInfoService;

    /**
     * 查询联系我们信息列表
     */
    //@RequiresPermissions("portalcontactUsInfo:list")
    @GetMapping("/list")
    public TableDataInfo list(HwContactUsInfo hwContactUsInfo)
    {
        startPage();
        List<HwContactUsInfo> list = hwContactUsInfoService.selectHwContactUsInfoList(hwContactUsInfo);
        return getDataTable(list);
    }

    /**
     * 导出联系我们信息列表
     */
    //@RequiresPermissions("portalcontactUsInfo:export")
    //@Log(title = "联系我们信息", businessType = BusinessType.EXPORT)
    @RepeatSubmit
    @PostMapping("/export")
    public void export(HttpServletResponse response, HwContactUsInfo hwContactUsInfo)
    {
        List<HwContactUsInfo> list = hwContactUsInfoService.selectHwContactUsInfoList(hwContactUsInfo);
        ExcelUtil<HwContactUsInfo> util = new ExcelUtil<HwContactUsInfo>(HwContactUsInfo.class);
        util.exportExcel(response, list, "联系我们信息数据");
    }

    /**
     * 获取联系我们信息详细信息
     */
    //@RequiresPermissions("portalcontactUsInfo:query")
    @GetMapping(value = "/{contactUsInfoId}")
    public AjaxResult getInfo(@PathVariable("contactUsInfoId") Long contactUsInfoId)
    {
        return success(hwContactUsInfoService.selectHwContactUsInfoByContactUsInfoId(contactUsInfoId));
    }

    /**
     * 新增联系我们信息
     */
    //@RequiresPermissions("portalcontactUsInfo:add")
    //@Log(title = "联系我们信息", businessType = BusinessType.INSERT)
    @RepeatSubmit
    @PostMapping
    public AjaxResult add(@RequestBody HwContactUsInfo hwContactUsInfo)
    {
        return toAjax(hwContactUsInfoService.insertHwContactUsInfo(hwContactUsInfo));
    }

    /**
     * 修改联系我们信息
     */
    //@RequiresPermissions("portalcontactUsInfo:edit")
    //@Log(title = "联系我们信息", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @PutMapping
    public AjaxResult edit(@RequestBody HwContactUsInfo hwContactUsInfo)
    {
        return toAjax(hwContactUsInfoService.updateHwContactUsInfo(hwContactUsInfo));
    }

    /**
     * 删除联系我们信息
     */
    //@RequiresPermissions("portalcontactUsInfo:remove")
    //@Log(title = "联系我们信息", businessType = BusinessType.DELETE)
	@RepeatSubmit
	@DeleteMapping("/{contactUsInfoIds}")
    public AjaxResult remove(@PathVariable Long[] contactUsInfoIds)
    {
        return toAjax(hwContactUsInfoService.deleteHwContactUsInfoByContactUsInfoIds(contactUsInfoIds));
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwPortalConfigController.java

package com.ruoyi.portal.controller;

import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.portal.domain.HwPortalConfig;
import com.ruoyi.portal.domain.HwPortalConfigType;
import com.ruoyi.portal.service.IHwPortalConfigService;
import com.ruoyi.portal.service.IHwPortalConfigTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;

/**
 * 门户网站配置Controller
 * 
 * @author xins
 * @date 2024-12-01
 */
@RestController
@RequestMapping("/portal/portalConfig")
@Anonymous//不需要登陆任何人都可以操作
public class HwPortalConfigController extends BaseController
{
    @Autowired
    private IHwPortalConfigService hwPortalConfigService;

    @Autowired
    private IHwPortalConfigTypeService hwPortalConfigTypeService;

    /**
     * 查询门户网站配置列表
     */
    //@RequiresPermissions("portalportalConfig:list")
    @GetMapping("/list")
    public TableDataInfo list(HwPortalConfig hwPortalConfig)
    {
        startPage();
        List<HwPortalConfig> list = hwPortalConfigService.selectHwPortalConfigJoinList(hwPortalConfig);
        return getDataTable(list);
    }

    /**
     * 导出门户网站配置列表
     */
    //@RequiresPermissions("portalportalConfig:export")
    //@Log(title = "门户网站配置", businessType = BusinessType.EXPORT)
    @RepeatSubmit
    @PostMapping("/export")
    public void export(HttpServletResponse response, HwPortalConfig hwPortalConfig)
    {
        List<HwPortalConfig> list = hwPortalConfigService.selectHwPortalConfigList(hwPortalConfig);
        ExcelUtil<HwPortalConfig> util = new ExcelUtil<HwPortalConfig>(HwPortalConfig.class);
        util.exportExcel(response, list, "门户网站配置数据");
    }

    /**
     * 获取门户网站配置详细信息
     */
    //@RequiresPermissions("portalportalConfig:query")
    @GetMapping(value = "/{portalConfigId}")
    public AjaxResult getInfo(@PathVariable("portalConfigId") Long portalConfigId)
    {
        return success(hwPortalConfigService.selectHwPortalConfigByPortalConfigId(portalConfigId));
    }

    /**
     * 新增门户网站配置
     */
    //@RequiresPermissions("portalportalConfig:add")
    //@Log(title = "门户网站配置", businessType = BusinessType.INSERT)
    @RepeatSubmit
    @PostMapping
    public AjaxResult add(@RequestBody HwPortalConfig hwPortalConfig)
    {
        return toAjax(hwPortalConfigService.insertHwPortalConfig(hwPortalConfig));
    }

    /**
     * 修改门户网站配置
     */
    //@RequiresPermissions("portalportalConfig:edit")
    //@Log(title = "门户网站配置", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @PutMapping
    public AjaxResult edit(@RequestBody HwPortalConfig hwPortalConfig)
    {
        return toAjax(hwPortalConfigService.updateHwPortalConfig(hwPortalConfig));
    }

    /**
     * 删除门户网站配置
     */
    //@RequiresPermissions("portalportalConfig:remove")
    //@Log(title = "门户网站配置", businessType = BusinessType.DELETE)
	@RepeatSubmit
	@DeleteMapping("/{portalConfigIds}")
    public AjaxResult remove(@PathVariable Long[] portalConfigIds)
    {
        return toAjax(hwPortalConfigService.deleteHwPortalConfigByPortalConfigIds(portalConfigIds));
    }


    /**
     * 获取门户网站配置树列表
     */
    //@RequiresPermissions("portalportalConfig:list")
    @GetMapping("/portalConfigTypeTree")
    public AjaxResult portalConfigTypeTree(HwPortalConfigType hwPortalConfigType) {

        return success(hwPortalConfigTypeService.selectPortalConfigTypeTreeList(hwPortalConfigType));
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwPortalConfigTypeController.java

package com.ruoyi.portal.controller;

import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.portal.domain.HwPortalConfigType;
import com.ruoyi.portal.service.IHwPortalConfigTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;

/**
 * 门户网站配置类型Controller
 * 
 * @author xins
 * @date 2024-12-11
 */
@RestController
@RequestMapping("/portal/portalConfigType")
@Anonymous//不需要登陆任何人都可以操作
public class HwPortalConfigTypeController extends BaseController
{
    @Autowired
    private IHwPortalConfigTypeService hwPortalConfigTypeService;

    /**
     * 查询门户网站配置类型列表
     */
    //@RequiresPermissions("portalportalConfigType:list")
    @GetMapping("/list")
    public AjaxResult list(HwPortalConfigType hwPortalConfigType)
    {
        List<HwPortalConfigType> list = hwPortalConfigTypeService.selectHwPortalConfigTypeList(hwPortalConfigType);
        return success(list);
    }

    /**
     * 导出门户网站配置类型列表
     */
    //@RequiresPermissions("portalportalConfigType:export")
    //@Log(title = "门户网站配置类型", businessType = BusinessType.EXPORT)
    @RepeatSubmit
    @PostMapping("/export")
    public void export(HttpServletResponse response, HwPortalConfigType hwPortalConfigType)
    {
        List<HwPortalConfigType> list = hwPortalConfigTypeService.selectHwPortalConfigTypeList(hwPortalConfigType);
        ExcelUtil<HwPortalConfigType> util = new ExcelUtil<HwPortalConfigType>(HwPortalConfigType.class);
        util.exportExcel(response, list, "门户网站配置类型数据");
    }

    /**
     * 获取门户网站配置类型详细信息
     */
    //@RequiresPermissions("portalportalConfigType:query")
    @GetMapping(value = "/{configTypeId}")
    public AjaxResult getInfo(@PathVariable("configTypeId") Long configTypeId)
    {
        return success(hwPortalConfigTypeService.selectHwPortalConfigTypeByConfigTypeId(configTypeId));
    }

    /**
     * 新增门户网站配置类型
     */
    //@RequiresPermissions("portalportalConfigType:add")
    //@Log(title = "门户网站配置类型", businessType = BusinessType.INSERT)
    @RepeatSubmit
    @PostMapping
    public AjaxResult add(@RequestBody HwPortalConfigType hwPortalConfigType)
    {
        return toAjax(hwPortalConfigTypeService.insertHwPortalConfigType(hwPortalConfigType));
    }

    /**
     * 修改门户网站配置类型
     */
    //@RequiresPermissions("portalportalConfigType:edit")
    //@Log(title = "门户网站配置类型", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @PutMapping
    public AjaxResult edit(@RequestBody HwPortalConfigType hwPortalConfigType)
    {
        return toAjax(hwPortalConfigTypeService.updateHwPortalConfigType(hwPortalConfigType));
    }

    /**
     * 删除门户网站配置类型
     */
    //@RequiresPermissions("portalportalConfigType:remove")
    //@Log(title = "门户网站配置类型", businessType = BusinessType.DELETE)
	@RepeatSubmit
	@DeleteMapping("/{configTypeIds}")
    public AjaxResult remove(@PathVariable Long[] configTypeIds)
    {
        return toAjax(hwPortalConfigTypeService.deleteHwPortalConfigTypeByConfigTypeIds(configTypeIds));
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwPortalController.java

package com.ruoyi.portal.controller;

import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.portal.domain.*;
import com.ruoyi.portal.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;

/**
 * 门户网站前端Controller
 * 
 * @author xins
 * @date 2024-12-12
 */
@RestController
@RequestMapping("/portal/portal")
@Anonymous//不需要登陆任何人都可以操作
public class HwPortalController extends BaseController
{
    @Autowired
    private IHwPortalConfigService hwPortalConfigService;

    @Autowired
    private IHwPortalConfigTypeService hwPortalConfigTypeService;

    @Autowired
    private IHwProductCaseInfoService hwProductCaseInfoService;

    @Autowired
    private IHwContactUsInfoService hwContactUsInfoService;

    @Autowired
    private IHwProductInfoService productInfoService;

    @Autowired
    private IHwProductInfoDetailService hwProductInfoDetailService;

    @Autowired
    private IHwAboutUsInfoService hwAboutUsInfoService;

    @Autowired
    private IHwAboutUsInfoDetailService hwAboutUsInfoDetailService;


    /**
     * 查询门户网站配置列表首页大图portal_config_type为1;产品中心大图portal_config_type为2,并且需要根据portalConfigTypeId获取
     */
    @GetMapping("/getPortalConfigList")
    public TableDataInfo getPortalConfigList(HwPortalConfig hwPortalConfig)
    {
        startPage();
        List<HwPortalConfig> list = hwPortalConfigService.selectHwPortalConfigList(hwPortalConfig);
        return getDataTable(list);
    }


    /**
     * 门户网站配置类型首页产品中心config_type_classfication为1按homeConfigTypeName显示产品中心页面上面的按configTypeName显示
     */
    @GetMapping("/getPortalConfigTypeList")
    public TableDataInfo getPortalConfigTypeList(HwPortalConfigType hwPortalConfigType)
    {
        List<HwPortalConfigType> list = hwPortalConfigTypeService.selectHwPortalConfigTypeList(hwPortalConfigType);
        return getDataTable(list);
    }


    /**
     * 门户网站配置类型首页产品中心config_type_classfication为1按homeConfigTypeName显示产品中心页面上面的按configTypeName显示
     */
    @GetMapping("/selectConfigTypeList")
    public TableDataInfo selectConfigTypeList(HwPortalConfigType hwPortalConfigType)
    {
        List<HwPortalConfigType> list = hwPortalConfigTypeService.selectConfigTypeList(hwPortalConfigType);
        return getDataTable(list);
    }

    /**
     * 获取首页案例tab title(例如物联网、制造中心和快递物流)
     */
    @GetMapping("/getHomeCaseTitleList")
    public TableDataInfo getHomeCaseTitleList(HwPortalConfigType hwPortalConfigType)
    {
        startPage();
        List<HwPortalConfigType> list = hwPortalConfigTypeService.selectHwPortalConfigTypeList(hwPortalConfigType);
        return getDataTable(list);
    }


    /**
     * 获取首页案例信息
     */
    @GetMapping("/getTypicalHomeCaseInfo")
    public AjaxResult getTypicalHomeCaseInfo(HwProductCaseInfo queryProductCaseInfo)
    {
        HwProductCaseInfo hwProductCaseInfo = hwProductCaseInfoService.getTypicalHomeCaseInfo(queryProductCaseInfo);

        return success(hwProductCaseInfo);
    }



    /**
     * 新增联系我们
     */
    //@Log(title = "联系我们", businessType = BusinessType.INSERT)
    @RepeatSubmit
    @PostMapping("/addContactUsInfo")
    public AjaxResult addContactUsInfo(@RequestBody HwContactUsInfo hwContactUsInfo)
    {
        hwContactUsInfo.setUserIp(IpUtils.getIpAddr());
        return toAjax(hwContactUsInfoService.insertHwContactUsInfo(hwContactUsInfo));
    }



    /**
     * 获取产品中心产品信息(平台简介,hw_product_info获取配置模式2左标题+内容右图片读取中文标题和英文标题下面内容从hw_product_info_detail获取读取标题内容和图片)
     */
    @GetMapping("/getProductCenterProductInfos")
    public AjaxResult getProductCenterProductInfos(HwProductInfo hwProductInfo)
    {
//        配置模式(1图标 +文字+内容横铺4个2左标题+内容右图片3左图标右标题+内容一行2个4左大图右标题+内容一行2个5上标题+下图片6上标题+内容下图片7图标标题内容一行3个,8左图右列表9上图下内容一行4个)
        return success(productInfoService.selectHwProductInfoJoinDetailList(hwProductInfo));
    }

    /**
     * 产品中心如果tab的话根据tab的product_info_detail_id获取children productinfodetail
     * @param hwProductInfoDetail
     * @return
     */
    @GetMapping("/getProductCenterProductDetailInfos")
    public AjaxResult getProductCenterProductDetailInfos(HwProductInfoDetail hwProductInfoDetail)
    {
//       productinfodetail的config_modal 配置模式(1图标 +文字+内容横铺4个2左标题+内容右图片3左图标右标题+内容一行2个4左大图右标题+内容一行2个5上标题+下图片6上标题+内容下图片7图标标题内容一行3个,8一张图9上图下内容一行4个)
        return success(hwProductInfoDetailService.selectHwProductInfoDetailList(hwProductInfoDetail));
    }


    /**
     * 产品中心如果tab的话根据tab的portalconfigtypeid获取productcaseinfo
     * @param hwProductCaseInfo
     * @return
     */
    @GetMapping("/getCaseCenterCaseInfos")
    public AjaxResult getCaseCenterCaseInfos(HwProductCaseInfo hwProductCaseInfo)
    {
        return success(hwProductCaseInfoService.selectHwProductCaseInfoList(hwProductCaseInfo));
    }

    /**
     * 根据案例ID获取案例详情
     * @param caseInfoId
     * @return
     */
    @GetMapping("/getCaseCenterCaseInfo/{caseInfoId}")
    public AjaxResult getCaseCenterCaseInfo(@PathVariable("caseInfoId") Long caseInfoId)
    {
        return success(hwProductCaseInfoService.selectHwProductCaseInfoByCaseInfoId(caseInfoId));
    }


    /**
     * 获取关于我们信息
     * @param hwAboutUsInfo
     * @return
     */
    @GetMapping("/getAboutUsInfo")
    public AjaxResult getAboutUsInfo(HwAboutUsInfo hwAboutUsInfo)
    {
        return success(hwAboutUsInfoService.selectHwAboutUsInfoList(hwAboutUsInfo));
    }


    /**
     * 获取关于我们信息详情
     * @param hwAboutUsInfoDetail
     * @return
     */
    @GetMapping("/getAboutUsInfoDetails")
    public AjaxResult getAboutUsInfoDetails(HwAboutUsInfoDetail hwAboutUsInfoDetail)
    {
        return success(hwAboutUsInfoDetailService.selectHwAboutUsInfoDetailList(hwAboutUsInfoDetail));
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwProductCaseInfoController.java

package com.ruoyi.portal.controller;

import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.portal.domain.HwPortalConfigType;
import com.ruoyi.portal.domain.HwProductCaseInfo;
import com.ruoyi.portal.service.IHwPortalConfigTypeService;
import com.ruoyi.portal.service.IHwProductCaseInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;

/**
 * 案例内容Controller
 * 
 * @author xins
 * @date 2024-12-01
 */
@RestController
@RequestMapping("/portal/productCaseInfo")
@Anonymous//不需要登陆任何人都可以操作
public class HwProductCaseInfoController extends BaseController
{
    @Autowired
    private IHwProductCaseInfoService hwProductCaseInfoService;

    @Autowired
    private IHwPortalConfigTypeService hwPortalConfigTypeService;

    /**
     * 查询案例内容列表
     */
    //@RequiresPermissions("portalproductCaseInfo:list")
    @GetMapping("/list")
    public TableDataInfo list(HwProductCaseInfo hwProductCaseInfo)
    {
        startPage();
        List<HwProductCaseInfo> list = hwProductCaseInfoService.selectHwProductCaseInfoList(hwProductCaseInfo);
        return getDataTable(list);
    }

    /**
     * 导出案例内容列表
     */
    //@RequiresPermissions("portalproductCaseInfo:export")
    //@Log(title = "案例内容", businessType = BusinessType.EXPORT)
    @RepeatSubmit
    @PostMapping("/export")
    public void export(HttpServletResponse response, HwProductCaseInfo hwProductCaseInfo)
    {
        List<HwProductCaseInfo> list = hwProductCaseInfoService.selectHwProductCaseInfoList(hwProductCaseInfo);
        ExcelUtil<HwProductCaseInfo> util = new ExcelUtil<HwProductCaseInfo>(HwProductCaseInfo.class);
        util.exportExcel(response, list, "案例内容数据");
    }

    /**
     * 获取案例内容详细信息
     */
    //@RequiresPermissions("portalproductCaseInfo:query")
    @GetMapping(value = "/{caseInfoId}")
    public AjaxResult getInfo(@PathVariable("caseInfoId") Long caseInfoId)
    {
        return success(hwProductCaseInfoService.selectHwProductCaseInfoByCaseInfoId(caseInfoId));
    }

    /**
     * 新增案例内容
     */
    //@RequiresPermissions("portalproductCaseInfo:add")
    //@Log(title = "案例内容", businessType = BusinessType.INSERT)
    @RepeatSubmit
    @PostMapping
    public AjaxResult add(@RequestBody HwProductCaseInfo hwProductCaseInfo)
    {
        return toAjax(hwProductCaseInfoService.insertHwProductCaseInfo(hwProductCaseInfo));
    }

    /**
     * 修改案例内容
     */
    //@RequiresPermissions("portalproductCaseInfo:edit")
    //@Log(title = "案例内容", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @PutMapping
    public AjaxResult edit(@RequestBody HwProductCaseInfo hwProductCaseInfo)
    {
        return toAjax(hwProductCaseInfoService.updateHwProductCaseInfo(hwProductCaseInfo));
    }

    /**
     * 删除案例内容
     */
    //@RequiresPermissions("portalproductCaseInfo:remove")
    //@Log(title = "案例内容", businessType = BusinessType.DELETE)
	@RepeatSubmit
	@DeleteMapping("/{caseInfoIds}")
    public AjaxResult remove(@PathVariable Long[] caseInfoIds)
    {
        return toAjax(hwProductCaseInfoService.deleteHwProductCaseInfoByCaseInfoIds(caseInfoIds));
    }


    /**
     * 查询门户网站配置类型s树列表
     */
    /**
     * 获取门户网站配置树列表
     */
    //@RequiresPermissions("portalproductCaseInfo:list")
    @GetMapping("/portalConfigTypeTree")
    public AjaxResult portalConfigTypeTree(HwPortalConfigType hwPortalConfigType) {

        return success(hwPortalConfigTypeService.selectPortalConfigTypeTreeList(hwPortalConfigType));
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwProductInfoController.java

package com.ruoyi.portal.controller;

import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.portal.domain.HwPortalConfigType;
import com.ruoyi.portal.domain.HwProductInfo;
import com.ruoyi.portal.service.IHwPortalConfigTypeService;
import com.ruoyi.portal.service.IHwProductInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;

/**
 * 产品信息配置Controller
 * 
 * @author xins
 * @date 2024-12-01
 */
@RestController
@RequestMapping("/portal/productInfo")
@Anonymous//不需要登陆任何人都可以操作
public class HwProductInfoController extends BaseController
{
    @Autowired
    private IHwProductInfoService hwProductInfoService;

    @Autowired
    private IHwPortalConfigTypeService hwPortalConfigTypeService;


    /**
     * 查询产品信息配置列表
     */
    //@RequiresPermissions("portalproductInfo:list")
    @GetMapping("/list")
    public TableDataInfo list(HwProductInfo hwProductInfo)
    {
        startPage();
        List<HwProductInfo> list = hwProductInfoService.selectHwProductInfoJoinList(hwProductInfo);
        return getDataTable(list);
    }

    /**
     * 导出产品信息配置列表
     */
    //@RequiresPermissions("portalproductInfo:export")
    //@Log(title = "产品信息配置", businessType = BusinessType.EXPORT)
    @RepeatSubmit
    @PostMapping("/export")
    public void export(HttpServletResponse response, HwProductInfo hwProductInfo)
    {
        List<HwProductInfo> list = hwProductInfoService.selectHwProductInfoList(hwProductInfo);
        ExcelUtil<HwProductInfo> util = new ExcelUtil<HwProductInfo>(HwProductInfo.class);
        util.exportExcel(response, list, "产品信息配置数据");
    }

    /**
     * 获取产品信息配置详细信息
     */
    //@RequiresPermissions("portalproductInfo:query")
    @GetMapping(value = "/{productInfoId}")
    public AjaxResult getInfo(@PathVariable("productInfoId") Long productInfoId)
    {
        return success(hwProductInfoService.selectHwProductInfoByProductInfoId(productInfoId));
    }

    /**
     * 新增产品信息配置
     */
    //@RequiresPermissions("portalproductInfo:add")
    //@Log(title = "产品信息配置", businessType = BusinessType.INSERT)
    @RepeatSubmit
    @PostMapping
    public AjaxResult add(@RequestBody HwProductInfo hwProductInfo)
    {
        return toAjax(hwProductInfoService.insertHwProductInfo(hwProductInfo));
    }

    /**
     * 修改产品信息配置
     */
    //@RequiresPermissions("portalproductInfo:edit")
    //@Log(title = "产品信息配置", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @PutMapping
    public AjaxResult edit(@RequestBody HwProductInfo hwProductInfo)
    {
        return toAjax(hwProductInfoService.updateHwProductInfo(hwProductInfo));
    }

    /**
     * 删除产品信息配置
     */
    //@RequiresPermissions("portalproductInfo:remove")
    //@Log(title = "产品信息配置", businessType = BusinessType.DELETE)
	@RepeatSubmit
	@DeleteMapping("/{productInfoIds}")
    public AjaxResult remove(@PathVariable Long[] productInfoIds)
    {
        return toAjax(hwProductInfoService.deleteHwProductInfoByProductInfoIds(productInfoIds));
    }


    /**
     * 查询门户网站配置类型s树列表
     */
    /**
     * 获取门户网站配置树列表
     */
    //@RequiresPermissions("portalproductInfo:list")
    @GetMapping("/portalConfigTypeTree")
    public AjaxResult portalConfigTypeTree(HwPortalConfigType hwPortalConfigType) {

        return success(hwPortalConfigTypeService.selectPortalConfigTypeTreeList(hwPortalConfigType));
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwProductInfoDetailController.java

package com.ruoyi.portal.controller;

import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.portal.domain.HwProductInfoDetail;
import com.ruoyi.portal.service.IHwProductInfoDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;

/**
 * 产品信息明细配置Controller
 * 
 * @author xins
 * @date 2024-12-11
 */
@RestController
@RequestMapping("/portal/productInfoDetail")
@Anonymous//不需要登陆任何人都可以操作
public class HwProductInfoDetailController extends BaseController
{
    @Autowired
    private IHwProductInfoDetailService hwProductInfoDetailService;

    /**
     * 查询产品信息明细配置列表
     */
    //@RequiresPermissions("portalproductInfoDetail:list")
    @GetMapping("/list")
    public AjaxResult list(HwProductInfoDetail hwProductInfoDetail)
    {
        List<HwProductInfoDetail> list = hwProductInfoDetailService.selectHwProductInfoDetailList(hwProductInfoDetail);
        return success(list);
    }

    /**
     * 导出产品信息明细配置列表
     */
    //@RequiresPermissions("portalproductInfoDetail:export")
    //@Log(title = "产品信息明细配置", businessType = BusinessType.EXPORT)
    @RepeatSubmit
    @PostMapping("/export")
    public void export(HttpServletResponse response, HwProductInfoDetail hwProductInfoDetail)
    {
        List<HwProductInfoDetail> list = hwProductInfoDetailService.selectHwProductInfoDetailList(hwProductInfoDetail);
        ExcelUtil<HwProductInfoDetail> util = new ExcelUtil<HwProductInfoDetail>(HwProductInfoDetail.class);
        util.exportExcel(response, list, "产品信息明细配置数据");
    }

    /**
     * 获取产品信息明细配置详细信息
     */
    //@RequiresPermissions("portalproductInfoDetail:query")
    @GetMapping(value = "/{productInfoDetailId}")
    public AjaxResult getInfo(@PathVariable("productInfoDetailId") Long productInfoDetailId)
    {
        return success(hwProductInfoDetailService.selectHwProductInfoDetailByProductInfoDetailId(productInfoDetailId));
    }

    /**
     * 新增产品信息明细配置
     */
    //@RequiresPermissions("portalproductInfoDetail:add")
    //@Log(title = "产品信息明细配置", businessType = BusinessType.INSERT)
    @RepeatSubmit
    @PostMapping
    public AjaxResult add(@RequestBody HwProductInfoDetail hwProductInfoDetail)
    {
        return toAjax(hwProductInfoDetailService.insertHwProductInfoDetail(hwProductInfoDetail));
    }

    /**
     * 修改产品信息明细配置
     */
    //@RequiresPermissions("portalproductInfoDetail:edit")
    //@Log(title = "产品信息明细配置", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @PutMapping
    public AjaxResult edit(@RequestBody HwProductInfoDetail hwProductInfoDetail)
    {
        return toAjax(hwProductInfoDetailService.updateHwProductInfoDetail(hwProductInfoDetail));
    }

    /**
     * 删除产品信息明细配置
     */
    //@RequiresPermissions("portalproductInfoDetail:remove")
    //@Log(title = "产品信息明细配置", businessType = BusinessType.DELETE)
	@RepeatSubmit
	@DeleteMapping("/{productInfoDetailIds}")
    public AjaxResult remove(@PathVariable Long[] productInfoDetailIds)
    {
        return toAjax(hwProductInfoDetailService.deleteHwProductInfoDetailByProductInfoDetailIds(productInfoDetailIds));
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwSearchAdminController.java

package com.ruoyi.portal.controller;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.portal.service.IHwSearchRebuildService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 搜索索引管理接口
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/portal/search/admin")
public class HwSearchAdminController extends BaseController
{
    private final IHwSearchRebuildService hwSearchRebuildService;

    public HwSearchAdminController(IHwSearchRebuildService hwSearchRebuildService)
    {
        this.hwSearchRebuildService = hwSearchRebuildService;
    }

    /**
     * 全量重建 ES 索引
     */
    @Log(title = "门户搜索索引", businessType = BusinessType.OTHER)
    @PostMapping("/rebuild")
    public AjaxResult rebuild()
    {
        hwSearchRebuildService.rebuildAll();
        return success("重建完成");
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwSearchController.java

package com.ruoyi.portal.controller;

import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RateLimiter;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.LimitType;
import com.ruoyi.portal.service.IHwSearchService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * 门户关键词搜索
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/portal/search")
@Anonymous
public class HwSearchController extends BaseController
{
    private final IHwSearchService hwSearchService;

    public HwSearchController(IHwSearchService hwSearchService)
    {
        this.hwSearchService = hwSearchService;
    }

    /**
     * 门户搜索(展示端)
     */
    @GetMapping
    @RateLimiter(key = "portal_search", time = 60, count = 120, limitType = LimitType.IP)
    public AjaxResult search(@RequestParam("keyword") String keyword,
                             @RequestParam(value = "pageNum", required = false) Integer pageNum,
                             @RequestParam(value = "pageSize", required = false) Integer pageSize)
    {
        return success(hwSearchService.search(keyword, pageNum, pageSize));
    }

    /**
     * 编辑端搜索
     */
    @GetMapping("/edit")
    @RateLimiter(key = "portal_search_edit", time = 60, count = 120, limitType = LimitType.IP)
    public AjaxResult editSearch(@RequestParam("keyword") String keyword,
                                 @RequestParam(value = "pageNum", required = false) Integer pageNum,
                                 @RequestParam(value = "pageSize", required = false) Integer pageSize)
    {
        return success(hwSearchService.searchForEdit(keyword, pageNum, pageSize));
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwWebController.java

package com.ruoyi.portal.controller;

import java.util.List;
import java.io.IOException;
import jakarta.servlet.http.HttpServletResponse;

import com.ruoyi.portal.domain.HwWeb1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.portal.domain.HwWeb;
import com.ruoyi.portal.service.IHwWebService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;

/**
 * haiwei官网jsonController
 * 
 * @author ruoyi
 * @date 2025-08-18
 */
@RestController
@RequestMapping("/portal/hwWeb")
@Anonymous//不需要登陆任何人都可以操作
public class HwWebController extends BaseController
{
    @Autowired
    private IHwWebService hwWebService;

    /**
     * 查询haiwei官网json列表
     */
    //@RequiresPermissions("portalhwWeb:list")
    @GetMapping("/list")
    public TableDataInfo list(HwWeb hwWeb)
    {
//        startPage();
        List<HwWeb> list = hwWebService.selectHwWebList(hwWeb);
        return getDataTable(list);
    }

    /**
     * 导出haiwei官网json列表
     */
    //@RequiresPermissions("portalhwWeb:export")
    //@Log(title = "haiwei官网json", businessType = BusinessType.EXPORT)
    @RepeatSubmit
    @PostMapping("/export")
    public void export(HttpServletResponse response, HwWeb hwWeb)
    {
        List<HwWeb> list = hwWebService.selectHwWebList(hwWeb);
        ExcelUtil<HwWeb> util = new ExcelUtil<HwWeb>(HwWeb.class);
        util.exportExcel(response, list, "haiwei官网json数据");
    }

    /**
     * 获取haiwei官网json详细信息
     */
    //@RequiresPermissions("portalhwWeb:query")
    @GetMapping(value = "/{webCode}")
    public AjaxResult getInfo(@PathVariable("webCode") Long webCode)
    {
        return success(hwWebService.selectHwWebByWebcode(webCode));
    }

    /**
     * 新增haiwei官网json
     */
    //@RequiresPermissions("portalhwWeb:add")
    //@Log(title = "haiwei官网json", businessType = BusinessType.INSERT)
    @RepeatSubmit
    @PostMapping
    public AjaxResult add(@RequestBody HwWeb hwWeb)
    {
        return toAjax(hwWebService.insertHwWeb(hwWeb));
    }

    /**
     * 修改haiwei官网json
     */
    //@RequiresPermissions("portalhwWeb:edit")
    //@Log(title = "haiwei官网json", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @PutMapping
    public AjaxResult edit(@RequestBody HwWeb hwWeb)
    {
        int i = hwWebService.updateHwWeb(hwWeb);
        return toAjax(i);
    }

    /**
     * 删除haiwei官网json
     */
    //@RequiresPermissions("portalhwWeb:remove")
    //@Log(title = "haiwei官网json", businessType = BusinessType.DELETE)
	@RepeatSubmit
	@DeleteMapping("/{webIds}")
    public AjaxResult remove(@PathVariable Long[] webIds)
    {
        return toAjax(hwWebService.deleteHwWebByWebIds(webIds));
    }

    @GetMapping("/getHwWebList")
    public AjaxResult getHwWebList(HwWeb HwWeb)
    {
        return success(hwWebService.selectHwWebList(HwWeb)) ;
    }

}

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwWebController1.java

package com.ruoyi.portal.controller;

import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.portal.domain.HwWeb1;
import com.ruoyi.portal.service.IHwWebService1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;

/**
 * haiwei官网jsonController
 * 
 * @author ruoyi
 * @date 2025-08-18
 */
@RestController
@RequestMapping("/portal/hwWeb1")
@Anonymous//不需要登陆任何人都可以操作
public class HwWebController1 extends BaseController
{

    @Autowired
    private IHwWebService1 hwWebService1;

    /**
     * 查询haiwei官网json列表
     */
    //@RequiresPermissions("portalhwWeb:list")
    @GetMapping("/list")
    public TableDataInfo list(HwWeb1 HwWeb1)
    {
//        startPage();
        List<HwWeb1> list = hwWebService1.selectHwWebList(HwWeb1);
        return getDataTable(list);
    }

    /**
     * 导出haiwei官网json列表
     */
    //@RequiresPermissions("portalhwWeb:export")
    //@Log(title = "haiwei官网json", businessType = BusinessType.EXPORT)
    @RepeatSubmit
    @PostMapping("/export")
    public void export(HttpServletResponse response, HwWeb1 HwWeb1)
    {
        List<HwWeb1> list = hwWebService1.selectHwWebList(HwWeb1);
        ExcelUtil<HwWeb1> util = new ExcelUtil<HwWeb1>(HwWeb1.class);
        util.exportExcel(response, list, "haiwei官网json数据");
    }

    /**
     * 获取haiwei官网json详细信息
     */
    //@RequiresPermissions("portalhwWeb:query")
    @GetMapping(value = "/{webCode}")
    public AjaxResult getInfo(@PathVariable("webCode") Long webCode)
    {
        return success(hwWebService1.selectHwWebByWebcode(webCode));
    }

    /**
     * 新增haiwei官网json
     */
    //@RequiresPermissions("portalhwWeb:add")
    //@Log(title = "haiwei官网json", businessType = BusinessType.INSERT)
    @RepeatSubmit
    @PostMapping
    public AjaxResult add(@RequestBody HwWeb1 HwWeb1)
    {
        return toAjax(hwWebService1.insertHwWeb(HwWeb1));
    }

    /**
     * 修改haiwei官网json
     */
    //@RequiresPermissions("portalhwWeb:edit")
    //@Log(title = "haiwei官网json", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @PutMapping
    public AjaxResult edit(@RequestBody HwWeb1 HwWeb1)
    {
        int i = hwWebService1.updateHwWeb(HwWeb1);
        return toAjax(i);
    }

    /**
     * 删除haiwei官网json
     */
    //@RequiresPermissions("portalhwWeb:remove")
    //@Log(title = "haiwei官网json", businessType = BusinessType.DELETE)
	@RepeatSubmit
	@DeleteMapping("/{webIds}")
    public AjaxResult remove(@PathVariable Long[] webIds)
    {
        return toAjax(hwWebService1.deleteHwWebByWebIds(webIds));
    }


    @GetMapping("/getHwWeb1List")
    public AjaxResult getHwWeb1List(HwWeb1 HwWeb1)
    {
        return success(hwWebService1.selectHwWebList(HwWeb1)) ;
    }

}

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwWebDocumentController.java

package com.ruoyi.portal.controller;

import java.util.List;
import java.io.IOException;
import jakarta.servlet.http.HttpServletResponse;

import com.ruoyi.portal.domain.SecureDocumentRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.portal.domain.HwWebDocument;
import com.ruoyi.portal.service.IHwWebDocumentService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;

/**
 * Hw资料文件Controller
 * 
 * @author zch
 * @date 2025-09-22
 */
@RestController
@RequestMapping("/portal/hwWebDocument")
@Anonymous//不需要登陆任何人都可以操作
public class HwWebDocumentController extends BaseController
{
    @Autowired
    private IHwWebDocumentService hwWebDocumentService;

    /**
     * 查询Hw资料文件列表
     */
//    @RequiresPermissions("portal:hwWebDocument:list")
    @GetMapping("/list")
    public TableDataInfo list(HwWebDocument hwWebDocument)
    {
        startPage();
        List<HwWebDocument> list = hwWebDocumentService.selectHwWebDocumentList(hwWebDocument);
        for (HwWebDocument doc : list) {
            // 隐藏密钥,若设置了密钥则隐藏文件地址
            doc.setSecretKey(null);
            if (doc.getHasSecret()) {
                doc.setDocumentAddress(null);
            }
        }
        return getDataTable(list);
    }

    /**
     * 导出Hw资料文件列表
     */
//    @RequiresPermissions("portal:hwWebDocument:export")
    //@Log(title = "Hw资料文件", businessType = BusinessType.EXPORT)
    @RepeatSubmit
    @PostMapping("/export")
    public void export(HttpServletResponse response, HwWebDocument hwWebDocument)
    {
        List<HwWebDocument> list = hwWebDocumentService.selectHwWebDocumentList(hwWebDocument);
        ExcelUtil<HwWebDocument> util = new ExcelUtil<HwWebDocument>(HwWebDocument.class);
        util.exportExcel(response, list, "Hw资料文件数据");
    }

    /**
     * 获取Hw资料文件详细信息
     */
//    @RequiresPermissions("portal:hwWebDocument:query")
    @GetMapping(value = "/{documentId}")
    public AjaxResult getInfo(@PathVariable("documentId") String documentId)
    {
        HwWebDocument doc = hwWebDocumentService.selectHwWebDocumentByDocumentId(documentId);
        if (doc != null) {
            // 隐藏密钥,若设置了密钥则隐藏文件地址
            doc.setSecretKey(null);
            if (doc.getHasSecret()) {
                doc.setDocumentAddress(null);
            }
        }
        return success(doc);
    }

    /**
     * 新增Hw资料文件
     */
//    @RequiresPermissions("portal:hwWebDocument:add")
    //@Log(title = "Hw资料文件", businessType = BusinessType.INSERT)
    @RepeatSubmit
    @PostMapping
    public AjaxResult add(@RequestBody HwWebDocument hwWebDocument)
    {
        return toAjax(hwWebDocumentService.insertHwWebDocument(hwWebDocument));
    }

    /**
     * 修改Hw资料文件
     */
//    @RequiresPermissions("portal:hwWebDocument:edit")
    //@Log(title = "Hw资料文件", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @PutMapping
    public AjaxResult edit(@RequestBody HwWebDocument hwWebDocument)
    {
        System.out.println(hwWebDocument.getSecretKey());
        return toAjax(hwWebDocumentService.updateHwWebDocument(hwWebDocument));
    }

    /**
     * 删除Hw资料文件
     */
//    @RequiresPermissions("portal:hwWebDocument:remove")
    //@Log(title = "Hw资料文件", businessType = BusinessType.DELETE)
	@RepeatSubmit
	@DeleteMapping("/{documentIds}")
    public AjaxResult remove(@PathVariable String[] documentIds)
    {
        return toAjax(hwWebDocumentService.deleteHwWebDocumentByDocumentIds(documentIds));
    }

        /**
     * 获取安全文件地址
     */
//    @RequiresPermissions("portal:hwWebDocument:query")
    //@Log(title = "获取安全文件地址", businessType = BusinessType.OTHER)
    @RepeatSubmit
    @PostMapping("/getSecureDocumentAddress")
    public AjaxResult getSecureDocumentAddress(@RequestBody SecureDocumentRequest request)
    {
        try {
            String address = hwWebDocumentService.verifyAndGetDocumentAddress(request.getDocumentId(), request.getProvidedKey());
            return success(address);
        } catch (Exception e) {
            return error(e.getMessage());
        }
    }

}

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwWebMenuController.java

package com.ruoyi.portal.controller;

import java.util.List;
import java.io.IOException;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.portal.domain.HwWebMenu;
import com.ruoyi.portal.service.IHwWebMenuService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;

/**
 * haiwei官网菜单Controller
 *
 * @author zch
 * @date 2025-08-18
 */
@RestController
@RequestMapping("/portal/hwWebMenu")
@Anonymous//不需要登陆任何人都可以操作
public class HwWebMenuController extends BaseController
{
    @Autowired
    private IHwWebMenuService hwWebMenuService;

    /**
     * 查询haiwei官网菜单列表
     */
    //@RequiresPermissions("portalhwWebMenu:list")
    @GetMapping("/list")
    public AjaxResult list(HwWebMenu hwWebMenu)
    {
        List<HwWebMenu> list = hwWebMenuService.selectHwWebMenuList(hwWebMenu);
        return success(list);
    }

    /**
     * 导出haiwei官网菜单列表
     */
    //@RequiresPermissions("portalhwWebMenu:export")
    //@Log(title = "haiwei官网菜单", businessType = BusinessType.EXPORT)
    @RepeatSubmit
    @PostMapping("/export")
    public void export(HttpServletResponse response, HwWebMenu hwWebMenu)
    {
        List<HwWebMenu> list = hwWebMenuService.selectHwWebMenuList(hwWebMenu);
        ExcelUtil<HwWebMenu> util = new ExcelUtil<HwWebMenu>(HwWebMenu.class);
        util.exportExcel(response, list, "haiwei官网菜单数据");
    }

    /**
     * 获取haiwei官网菜单详细信息
     */
    //@RequiresPermissions("portalhwWebMenu:query")
    @GetMapping(value = "/{webMenuId}")
    public AjaxResult getInfo(@PathVariable("webMenuId") Long webMenuId)
    {
        return success(hwWebMenuService.selectHwWebMenuByWebMenuId(webMenuId));
    }

    /**
     * 新增haiwei官网菜单
     */
    //@RequiresPermissions("portalhwWebMenu:add")
    //@Log(title = "haiwei官网菜单", businessType = BusinessType.INSERT)
    @RepeatSubmit
    @PostMapping
    public AjaxResult add(@RequestBody HwWebMenu hwWebMenu)
    {
        return toAjax(hwWebMenuService.insertHwWebMenu(hwWebMenu));
    }

    /**
     * 修改haiwei官网菜单
     */
    //@RequiresPermissions("portalhwWebMenu:edit")
    //@Log(title = "haiwei官网菜单", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @PutMapping
    public AjaxResult edit(@RequestBody HwWebMenu hwWebMenu)
    {
        return toAjax(hwWebMenuService.updateHwWebMenu(hwWebMenu));
    }

    /**
     * 删除haiwei官网菜单
     */
    //@RequiresPermissions("portalhwWebMenu:remove")
    //@Log(title = "haiwei官网菜单", businessType = BusinessType.DELETE)
    @RepeatSubmit
    @DeleteMapping("/{webMenuIds}")
    public AjaxResult remove(@PathVariable Long[] webMenuIds)
    {
        return toAjax(hwWebMenuService.deleteHwWebMenuByWebMenuIds(webMenuIds));
    }

    /**
     * 获取菜单树列表
     */
    @GetMapping("/selectMenuTree")
    public AjaxResult selectMenuTree(HwWebMenu hwWebMenu){
        return success(hwWebMenuService.selectMenuTree(hwWebMenu));
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/controller/HwWebMenuController1.java

package com.ruoyi.portal.controller;

import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.portal.domain.HwWebMenu1;
import com.ruoyi.portal.service.IHwWebMenuService1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;

/**
 * haiwei官网菜单Controller
 *
 * @author zch
 * @date 2025-08-18
 */
@RestController
@RequestMapping("/portal/hwWebMenu1")
@Anonymous//不需要登陆任何人都可以操作
public class HwWebMenuController1 extends BaseController
{
    @Autowired
    private IHwWebMenuService1 hwWebMenuService1;

    /**
     * 查询haiwei官网菜单列表
     */
    //@RequiresPermissions("portalhwWebMenu:list")
    @GetMapping("/list")
    public AjaxResult list(HwWebMenu1 hwWebMenu1)
    {
        List<HwWebMenu1> list = hwWebMenuService1.selectHwWebMenuList(hwWebMenu1);
        return success(list);
    }

    /**
     * 导出haiwei官网菜单列表
     */
    //@RequiresPermissions("portalhwWebMenu:export")
    //@Log(title = "haiwei官网菜单", businessType = BusinessType.EXPORT)
    @RepeatSubmit
    @PostMapping("/export")
    public void export(HttpServletResponse response, HwWebMenu1 hwWebMenu1)
    {
        List<HwWebMenu1> list = hwWebMenuService1.selectHwWebMenuList(hwWebMenu1);
        ExcelUtil<HwWebMenu1> util = new ExcelUtil<HwWebMenu1>(HwWebMenu1.class);
        util.exportExcel(response, list, "haiwei官网菜单数据");
    }

    /**
     * 获取haiwei官网菜单详细信息
     */
    //@RequiresPermissions("portalhwWebMenu:query")
    @GetMapping(value = "/{webMenuId}")
    public AjaxResult getInfo(@PathVariable("webMenuId") Long webMenuId)
    {
        return success(hwWebMenuService1.selectHwWebMenuByWebMenuId(webMenuId));
    }

    /**
     * 新增haiwei官网菜单
     */
    //@RequiresPermissions("portalhwWebMenu:add")
    //@Log(title = "haiwei官网菜单", businessType = BusinessType.INSERT)
    @RepeatSubmit
    @PostMapping
    public AjaxResult add(@RequestBody HwWebMenu1 hwWebMenu1)
    {
        return toAjax(hwWebMenuService1.insertHwWebMenu(hwWebMenu1));
    }

    /**
     * 修改haiwei官网菜单
     */
    //@RequiresPermissions("portalhwWebMenu:edit")
    //@Log(title = "haiwei官网菜单", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @PutMapping
    public AjaxResult edit(@RequestBody HwWebMenu1 hwWebMenu1)
    {
        return toAjax(hwWebMenuService1.updateHwWebMenu(hwWebMenu1));
    }

    /**
     * 删除haiwei官网菜单
     */
    //@RequiresPermissions("portalhwWebMenu:remove")
    //@Log(title = "haiwei官网菜单", businessType = BusinessType.DELETE)
    @RepeatSubmit
    @DeleteMapping("/{webMenuIds}")
    public AjaxResult remove(@PathVariable Long[] webMenuIds)
    {
        return toAjax(hwWebMenuService1.deleteHwWebMenuByWebMenuIds(webMenuIds));
    }

    /**
     * 获取菜单树列表
     */
    @GetMapping("/selectMenuTree")
    public AjaxResult selectMenuTree(HwWebMenu1 hwWebMenu1){
        return success(hwWebMenuService1.selectMenuTree(hwWebMenu1));
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/dto/AnalyticsCollectRequest.java

package com.ruoyi.portal.domain.dto;

/**
 * 匿名访问采集请求
 *
 * @author ruoyi
 */
public class AnalyticsCollectRequest
{
    private String visitorId;

    private String sessionId;

    private String eventType;

    private String path;

    private String referrer;

    private String utmSource;

    private String utmMedium;

    private String utmCampaign;

    private String keyword;

    private String ua;

    private String device;

    private String browser;

    private String os;

    private Long stayMs;

    /** 毫秒时间戳 */
    private Long eventTime;

    public String getVisitorId()
    {
        return visitorId;
    }

    public void setVisitorId(String visitorId)
    {
        this.visitorId = visitorId;
    }

    public String getSessionId()
    {
        return sessionId;
    }

    public void setSessionId(String sessionId)
    {
        this.sessionId = sessionId;
    }

    public String getEventType()
    {
        return eventType;
    }

    public void setEventType(String eventType)
    {
        this.eventType = eventType;
    }

    public String getPath()
    {
        return path;
    }

    public void setPath(String path)
    {
        this.path = path;
    }

    public String getReferrer()
    {
        return referrer;
    }

    public void setReferrer(String referrer)
    {
        this.referrer = referrer;
    }

    public String getUtmSource()
    {
        return utmSource;
    }

    public void setUtmSource(String utmSource)
    {
        this.utmSource = utmSource;
    }

    public String getUtmMedium()
    {
        return utmMedium;
    }

    public void setUtmMedium(String utmMedium)
    {
        this.utmMedium = utmMedium;
    }

    public String getUtmCampaign()
    {
        return utmCampaign;
    }

    public void setUtmCampaign(String utmCampaign)
    {
        this.utmCampaign = utmCampaign;
    }

    public String getKeyword()
    {
        return keyword;
    }

    public void setKeyword(String keyword)
    {
        this.keyword = keyword;
    }

    public String getUa()
    {
        return ua;
    }

    public void setUa(String ua)
    {
        this.ua = ua;
    }

    public String getDevice()
    {
        return device;
    }

    public void setDevice(String device)
    {
        this.device = device;
    }

    public String getBrowser()
    {
        return browser;
    }

    public void setBrowser(String browser)
    {
        this.browser = browser;
    }

    public String getOs()
    {
        return os;
    }

    public void setOs(String os)
    {
        this.os = os;
    }

    public Long getStayMs()
    {
        return stayMs;
    }

    public void setStayMs(Long stayMs)
    {
        this.stayMs = stayMs;
    }

    public Long getEventTime()
    {
        return eventTime;
    }

    public void setEventTime(Long eventTime)
    {
        this.eventTime = eventTime;
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/dto/AnalyticsDashboardDTO.java

package com.ruoyi.portal.domain.dto;

import java.util.ArrayList;
import java.util.List;

/**
 * 官网访问监控看板
 *
 * @author ruoyi
 */
public class AnalyticsDashboardDTO
{
    private String statDate;

    private Long pv;

    private Long uv;

    private Long ipUv;

    private Long avgStayMs;

    private Double bounceRate;

    private Long searchCount;

    private Long downloadCount;

    private List<AnalyticsRankItemDTO> entryPages = new ArrayList<>();

    private List<AnalyticsRankItemDTO> hotPages = new ArrayList<>();

    private List<AnalyticsRankItemDTO> hotKeywords = new ArrayList<>();

    public String getStatDate()
    {
        return statDate;
    }

    public void setStatDate(String statDate)
    {
        this.statDate = statDate;
    }

    public Long getPv()
    {
        return pv;
    }

    public void setPv(Long pv)
    {
        this.pv = pv;
    }

    public Long getUv()
    {
        return uv;
    }

    public void setUv(Long uv)
    {
        this.uv = uv;
    }

    public Long getIpUv()
    {
        return ipUv;
    }

    public void setIpUv(Long ipUv)
    {
        this.ipUv = ipUv;
    }

    public Long getAvgStayMs()
    {
        return avgStayMs;
    }

    public void setAvgStayMs(Long avgStayMs)
    {
        this.avgStayMs = avgStayMs;
    }

    public Double getBounceRate()
    {
        return bounceRate;
    }

    public void setBounceRate(Double bounceRate)
    {
        this.bounceRate = bounceRate;
    }

    public Long getSearchCount()
    {
        return searchCount;
    }

    public void setSearchCount(Long searchCount)
    {
        this.searchCount = searchCount;
    }

    public Long getDownloadCount()
    {
        return downloadCount;
    }

    public void setDownloadCount(Long downloadCount)
    {
        this.downloadCount = downloadCount;
    }

    public List<AnalyticsRankItemDTO> getEntryPages()
    {
        return entryPages;
    }

    public void setEntryPages(List<AnalyticsRankItemDTO> entryPages)
    {
        this.entryPages = entryPages;
    }

    public List<AnalyticsRankItemDTO> getHotPages()
    {
        return hotPages;
    }

    public void setHotPages(List<AnalyticsRankItemDTO> hotPages)
    {
        this.hotPages = hotPages;
    }

    public List<AnalyticsRankItemDTO> getHotKeywords()
    {
        return hotKeywords;
    }

    public void setHotKeywords(List<AnalyticsRankItemDTO> hotKeywords)
    {
        this.hotKeywords = hotKeywords;
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/dto/AnalyticsRankItemDTO.java

package com.ruoyi.portal.domain.dto;

/**
 * 统计排行项
 *
 * @author ruoyi
 */
public class AnalyticsRankItemDTO
{
    private String name;

    private Long value;

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public Long getValue()
    {
        return value;
    }

    public void setValue(Long value)
    {
        this.value = value;
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/dto/SearchPageDTO.java

package com.ruoyi.portal.domain.dto;

import java.util.ArrayList;
import java.util.List;

/**
 * 搜索分页数据
 *
 * @author ruoyi
 */
public class SearchPageDTO
{
    /** 总记录数 */
    private long total;

    /** 结果列表 */
    private List<SearchResultDTO> rows = new ArrayList<>();

    public long getTotal()
    {
        return total;
    }

    public void setTotal(long total)
    {
        this.total = total;
    }

    public List<SearchResultDTO> getRows()
    {
        return rows;
    }

    public void setRows(List<SearchResultDTO> rows)
    {
        this.rows = rows;
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/dto/SearchRawRecord.java

package com.ruoyi.portal.domain.dto;

import java.util.Date;

/**
 * 搜索原始记录
 *
 * @author ruoyi
 */
public class SearchRawRecord
{
    private String sourceType;

    private String bizId;

    private String title;

    private String content;

    private String webCode;

    private String typeId;

    private String deviceId;

    private String menuId;

    private String documentId;

    private Integer score;

    private Date updatedAt;

    public String getSourceType()
    {
        return sourceType;
    }

    public void setSourceType(String sourceType)
    {
        this.sourceType = sourceType;
    }

    public String getBizId()
    {
        return bizId;
    }

    public void setBizId(String bizId)
    {
        this.bizId = bizId;
    }

    public String getTitle()
    {
        return title;
    }

    public void setTitle(String title)
    {
        this.title = title;
    }

    public String getContent()
    {
        return content;
    }

    public void setContent(String content)
    {
        this.content = content;
    }

    public String getWebCode()
    {
        return webCode;
    }

    public void setWebCode(String webCode)
    {
        this.webCode = webCode;
    }

    public String getTypeId()
    {
        return typeId;
    }

    public void setTypeId(String typeId)
    {
        this.typeId = typeId;
    }

    public String getDeviceId()
    {
        return deviceId;
    }

    public void setDeviceId(String deviceId)
    {
        this.deviceId = deviceId;
    }

    public String getMenuId()
    {
        return menuId;
    }

    public void setMenuId(String menuId)
    {
        this.menuId = menuId;
    }

    public String getDocumentId()
    {
        return documentId;
    }

    public void setDocumentId(String documentId)
    {
        this.documentId = documentId;
    }

    public Integer getScore()
    {
        return score;
    }

    public void setScore(Integer score)
    {
        this.score = score;
    }

    public Date getUpdatedAt()
    {
        return updatedAt;
    }

    public void setUpdatedAt(Date updatedAt)
    {
        this.updatedAt = updatedAt;
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/dto/SearchResultDTO.java

package com.ruoyi.portal.domain.dto;

import java.util.Map;

/**
 * 门户搜索结果
 *
 * @author ruoyi
 */
public class SearchResultDTO
{
    /** 来源类型 menu/web/web1/document/configType/productInfo/productDetail/caseInfo/aboutUs */
    private String sourceType;

    /** 标题 */
    private String title;

    /** 命中摘要 */
    private String snippet;

    /** 相关度分值 */
    private Integer score;

    /** 展示端跳转路由 */
    private String route;

    /** 展示端路由参数 */
    private Map<String, Object> routeQuery;

    /** 编辑端跳转路由 */
    private String editRoute;

    public String getSourceType()
    {
        return sourceType;
    }

    public void setSourceType(String sourceType)
    {
        this.sourceType = sourceType;
    }

    public String getTitle()
    {
        return title;
    }

    public void setTitle(String title)
    {
        this.title = title;
    }

    public String getSnippet()
    {
        return snippet;
    }

    public void setSnippet(String snippet)
    {
        this.snippet = snippet;
    }

    public Integer getScore()
    {
        return score;
    }

    public void setScore(Integer score)
    {
        this.score = score;
    }

    public String getRoute()
    {
        return route;
    }

    public void setRoute(String route)
    {
        this.route = route;
    }

    public Map<String, Object> getRouteQuery()
    {
        return routeQuery;
    }

    public void setRouteQuery(Map<String, Object> routeQuery)
    {
        this.routeQuery = routeQuery;
    }

    public String getEditRoute()
    {
        return editRoute;
    }

    public void setEditRoute(String editRoute)
    {
        this.editRoute = editRoute;
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/HwAboutUsInfo.java

package com.ruoyi.portal.domain;

import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

/**
 * 关于我们信息对象 hw_about_us_info
 * 
 * @author xins
 * @date 2024-12-01
 */
public class HwAboutUsInfo extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    /** 主键标识 */
    private Long aboutUsInfoId;

    /** 类型1关于我们页面上大图2公司简介3企业资质4认证证书5团队风貌 */
    @Excel(name = "类型", readConverterExp = "1=关于我们页面上大图2公司简介3企业资质4认证证书5团队风貌")
    private String aboutUsInfoType;

    /** 英文标题 */
    @Excel(name = "英文标题")
    private String aboutUsInfoEtitle;


    /** 中文标题 */
    @Excel(name = "中文标题")
    private String aboutUsInfoTitle;

    /** 内容 */
    @Excel(name = "内容")
    private String aboutUsInfoDesc;

    /** 顺序 */
    @Excel(name = "顺序")
    private Long aboutUsInfoOrder;

    /** 显示模式 */
    @Excel(name = "显示模式")
    private String displayModal;

    /** 图片地址 */
    @Excel(name = "图片地址")
    private String aboutUsInfoPic;

    public void setAboutUsInfoId(Long aboutUsInfoId) 
    {
        this.aboutUsInfoId = aboutUsInfoId;
    }

    public Long getAboutUsInfoId() 
    {
        return aboutUsInfoId;
    }
    public void setAboutUsInfoType(String aboutUsInfoType) 
    {
        this.aboutUsInfoType = aboutUsInfoType;
    }

    public String getAboutUsInfoType() 
    {
        return aboutUsInfoType;
    }

    public String getAboutUsInfoEtitle() {
        return aboutUsInfoEtitle;
    }

    public void setAboutUsInfoEtitle(String aboutUsInfoEtitle) {
        this.aboutUsInfoEtitle = aboutUsInfoEtitle;
    }

    public void setAboutUsInfoTitle(String aboutUsInfoTitle)
    {
        this.aboutUsInfoTitle = aboutUsInfoTitle;
    }

    public String getAboutUsInfoTitle() 
    {
        return aboutUsInfoTitle;
    }
    public void setAboutUsInfoDesc(String aboutUsInfoDesc) 
    {
        this.aboutUsInfoDesc = aboutUsInfoDesc;
    }

    public String getAboutUsInfoDesc() 
    {
        return aboutUsInfoDesc;
    }
    public void setAboutUsInfoOrder(Long aboutUsInfoOrder) 
    {
        this.aboutUsInfoOrder = aboutUsInfoOrder;
    }

    public Long getAboutUsInfoOrder() 
    {
        return aboutUsInfoOrder;
    }

    public String getDisplayModal() {
        return displayModal;
    }

    public void setDisplayModal(String displayModal) {
        this.displayModal = displayModal;
    }

    public void setAboutUsInfoPic(String aboutUsInfoPic)
    {
        this.aboutUsInfoPic = aboutUsInfoPic;
    }

    public String getAboutUsInfoPic() 
    {
        return aboutUsInfoPic;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("aboutUsInfoId", getAboutUsInfoId())
            .append("aboutUsInfoType", getAboutUsInfoType())
            .append("aboutUsInfoTitle", getAboutUsInfoTitle())
            .append("aboutUsInfoDesc", getAboutUsInfoDesc())
            .append("aboutUsInfoOrder", getAboutUsInfoOrder())
            .append("aboutUsInfoPic", getAboutUsInfoPic())
            .append("createTime", getCreateTime())
            .append("createBy", getCreateBy())
            .append("updateTime", getUpdateTime())
            .append("updateBy", getUpdateBy())
            .toString();
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/HwAboutUsInfoDetail.java

package com.ruoyi.portal.domain;

import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

/**
 * 关于我们信息明细对象 hw_about_us_info_detail
 * 
 * @author ruoyi
 * @date 2024-12-01
 */
public class HwAboutUsInfoDetail extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    /** 主键标识 */
    private Long usInfoDetailId;

    /** 关于我们信息ID */
    @Excel(name = "关于我们信息ID")
    private Long aboutUsInfoId;

    /** 标题 */
    @Excel(name = "标题")
    private String usInfoDetailTitle;

    /** 内容 */
    @Excel(name = "内容")
    private String usInfoDetailDesc;

    /** 顺序 */
    @Excel(name = "顺序")
    private Long usInfoDetailOrder;

    /** 图片地址 */
    @Excel(name = "图片地址")
    private String usInfoDetailPic;

    public void setUsInfoDetailId(Long usInfoDetailId) 
    {
        this.usInfoDetailId = usInfoDetailId;
    }

    public Long getUsInfoDetailId() 
    {
        return usInfoDetailId;
    }
    public void setAboutUsInfoId(Long aboutUsInfoId) 
    {
        this.aboutUsInfoId = aboutUsInfoId;
    }

    public Long getAboutUsInfoId() 
    {
        return aboutUsInfoId;
    }
    public void setUsInfoDetailTitle(String usInfoDetailTitle) 
    {
        this.usInfoDetailTitle = usInfoDetailTitle;
    }

    public String getUsInfoDetailTitle() 
    {
        return usInfoDetailTitle;
    }
    public void setUsInfoDetailDesc(String usInfoDetailDesc) 
    {
        this.usInfoDetailDesc = usInfoDetailDesc;
    }

    public String getUsInfoDetailDesc() 
    {
        return usInfoDetailDesc;
    }
    public void setUsInfoDetailOrder(Long usInfoDetailOrder) 
    {
        this.usInfoDetailOrder = usInfoDetailOrder;
    }

    public Long getUsInfoDetailOrder() 
    {
        return usInfoDetailOrder;
    }
    public void setUsInfoDetailPic(String usInfoDetailPic) 
    {
        this.usInfoDetailPic = usInfoDetailPic;
    }

    public String getUsInfoDetailPic() 
    {
        return usInfoDetailPic;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("usInfoDetailId", getUsInfoDetailId())
            .append("aboutUsInfoId", getAboutUsInfoId())
            .append("usInfoDetailTitle", getUsInfoDetailTitle())
            .append("usInfoDetailDesc", getUsInfoDetailDesc())
            .append("usInfoDetailOrder", getUsInfoDetailOrder())
            .append("usInfoDetailPic", getUsInfoDetailPic())
            .append("createTime", getCreateTime())
            .append("createBy", getCreateBy())
            .append("updateTime", getUpdateTime())
            .append("updateBy", getUpdateBy())
            .toString();
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/HwContactUsInfo.java

package com.ruoyi.portal.domain;

import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

/**
 * 联系我们信息对象 hw_contact_us_info
 * 
 * @author xins
 * @date 2024-12-01
 */
public class HwContactUsInfo extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    /** 主键标识 */
    private Long contactUsInfoId;

    /** 用户姓名 */
    @Excel(name = "用户姓名")
    private String userName;

    /** 邮箱 */
    @Excel(name = "邮箱")
    private String userEmail;

    /** 手机号 */
    @Excel(name = "手机号")
    private String userPhone;

    /** IP地址 */
    @Excel(name = "IP地址")
    private String userIp;

    private String remark;

    public void setContactUsInfoId(Long contactUsInfoId) 
    {
        this.contactUsInfoId = contactUsInfoId;
    }

    public Long getContactUsInfoId() 
    {
        return contactUsInfoId;
    }
    public void setUserName(String userName) 
    {
        this.userName = userName;
    }

    public String getUserName() 
    {
        return userName;
    }
    public void setUserEmail(String userEmail) 
    {
        this.userEmail = userEmail;
    }

    public String getUserEmail() 
    {
        return userEmail;
    }
    public void setUserPhone(String userPhone) 
    {
        this.userPhone = userPhone;
    }

    public String getUserPhone() 
    {
        return userPhone;
    }
    public void setUserIp(String userIp) 
    {
        this.userIp = userIp;
    }

    public String getUserIp() 
    {
        return userIp;
    }

    @Override
    public String getRemark() {
        return remark;
    }

    @Override
    public void setRemark(String remark) {
        this.remark = remark;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("contactUsInfoId", getContactUsInfoId())
            .append("userName", getUserName())
            .append("userEmail", getUserEmail())
            .append("userPhone", getUserPhone())
            .append("userIp", getUserIp())
            .append("createTime", getCreateTime())
            .append("createBy", getCreateBy())
            .append("updateTime", getUpdateTime())
            .append("updateBy", getUpdateBy())
            .toString();
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/HwPortalConfig.java

package com.ruoyi.portal.domain;

import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

/**
 * 门户网站配置对象 hw_portal_config
 * 
 * @author xins
 * @date 2024-12-01
 */
public class HwPortalConfig extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    /** 主键标识 */
    private Long portalConfigId;

    /** 类型(1首页大图 2产品中心大图) */
    @Excel(name = "类型(1首页大图 2产品中心大图)")
    private String portalConfigType;

    /**如果类型是2的则需要关联hw_portal_config_type*/
    private Long portalConfigTypeId;

    /** 标题 */
    @Excel(name = "标题")
    private String portalConfigTitle;

    /** 顺序 */
    @Excel(name = "顺序")
    private Long portalConfigOrder;

    /** 内容 */
    @Excel(name = "内容")
    private String portalConfigDesc;

    /** 按钮名称 */
    @Excel(name = "按钮名称")
    private String buttonName;

    /** 按钮跳转地址 */
    @Excel(name = "按钮跳转地址")
    private String routerAddress;

    /** 主图地址 */
    @Excel(name = "主图地址")
    private String portalConfigPic;

    private String configTypeName;


    private String homeConfigTypePic;
    private String homeConfigTypeIcon;
    private String homeConfigTypeName;
    private String homeConfigTypeClassfication;
    private Long parentId;
    private String ancestors;

    public void setPortalConfigId(Long portalConfigId) 
    {
        this.portalConfigId = portalConfigId;
    }

    public Long getPortalConfigId() 
    {
        return portalConfigId;
    }
    public void setPortalConfigType(String portalConfigType) 
    {
        this.portalConfigType = portalConfigType;
    }

    public String getPortalConfigType() 
    {
        return portalConfigType;
    }

    public Long getPortalConfigTypeId() {
        return portalConfigTypeId;
    }

    public void setPortalConfigTypeId(Long portalConfigTypeId) {
        this.portalConfigTypeId = portalConfigTypeId;
    }

    public void setPortalConfigTitle(String portalConfigTitle)
    {
        this.portalConfigTitle = portalConfigTitle;
    }

    public String getPortalConfigTitle() 
    {
        return portalConfigTitle;
    }
    public void setPortalConfigOrder(Long portalConfigOrder) 
    {
        this.portalConfigOrder = portalConfigOrder;
    }

    public Long getPortalConfigOrder() 
    {
        return portalConfigOrder;
    }
    public void setPortalConfigDesc(String portalConfigDesc) 
    {
        this.portalConfigDesc = portalConfigDesc;
    }

    public String getPortalConfigDesc() 
    {
        return portalConfigDesc;
    }
    public void setButtonName(String buttonName) 
    {
        this.buttonName = buttonName;
    }

    public String getButtonName() 
    {
        return buttonName;
    }
    public void setRouterAddress(String routerAddress) 
    {
        this.routerAddress = routerAddress;
    }

    public String getRouterAddress() 
    {
        return routerAddress;
    }
    public void setPortalConfigPic(String portalConfigPic) 
    {
        this.portalConfigPic = portalConfigPic;
    }

    public String getPortalConfigPic() 
    {
        return portalConfigPic;
    }

    public String getConfigTypeName() {
        return configTypeName;
    }

    public void setConfigTypeName(String configTypeName) {
        this.configTypeName = configTypeName;
    }


    public String getHomeConfigTypePic() {
        return homeConfigTypePic;
    }

    public void setHomeConfigTypePic(String homeConfigTypePic) {
        this.homeConfigTypePic = homeConfigTypePic;
    }

    public String getHomeConfigTypeIcon() {
        return homeConfigTypeIcon;
    }

    public void setHomeConfigTypeIcon(String homeConfigTypeIcon) {
        this.homeConfigTypeIcon = homeConfigTypeIcon;
    }

    public String getHomeConfigTypeName() {
        return homeConfigTypeName;
    }

    public void setHomeConfigTypeName(String homeConfigTypeName) {
        this.homeConfigTypeName = homeConfigTypeName;
    }

    public String getHomeConfigTypeClassfication() {
        return homeConfigTypeClassfication;
    }

    public void setHomeConfigTypeClassfication(String homeConfigTypeClassfication) {
        this.homeConfigTypeClassfication = homeConfigTypeClassfication;
    }

    public Long getParentId() {
        return parentId;
    }

    public void setParentId(Long parentId) {
        this.parentId = parentId;
    }

    public String getAncestors() {
        return ancestors;
    }

    public void setAncestors(String ancestors) {
        this.ancestors = ancestors;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("portalConfigId", getPortalConfigId())
            .append("portalConfigType", getPortalConfigType())
            .append("portalConfigTitle", getPortalConfigTitle())
            .append("portalConfigOrder", getPortalConfigOrder())
            .append("portalConfigDesc", getPortalConfigDesc())
            .append("buttonName", getButtonName())
            .append("routerAddress", getRouterAddress())
            .append("portalConfigPic", getPortalConfigPic())
            .append("createTime", getCreateTime())
            .append("createBy", getCreateBy())
            .append("updateTime", getUpdateTime())
            .append("updateBy", getUpdateBy())
                .append("configTypeName", getConfigTypeName())
                .append("homeConfigTypePic", getHomeConfigTypePic())
                .append("homeConfigTypeIcon", getHomeConfigTypeIcon())
                .append("homeConfigTypeName", getHomeConfigTypeName())
                .append("homeConfigTypeClassfication", getHomeConfigTypeClassfication())
                .append("parentId", getParentId())
                .append("ancestors", getAncestors())
            .toString();
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/HwPortalConfigType.java

package com.ruoyi.portal.domain;

import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.TreeEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import java.util.ArrayList;
import java.util.List;

/**
 * 门户网站配置类型对象 hw_portal_config_type
 * 
 * @author xins
 * @date 2024-12-11
 */
public class HwPortalConfigType extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    /** 主键标识 */
    private Long configTypeId;

    /** 大类(1产品中心2案例) */
    @Excel(name = "大类(1产品中心2案例)")
    private String configTypeClassfication;

    /** 名称 */
    @Excel(name = "名称")
    private String configTypeName;

    /** 首页名称 */
    @Excel(name = "首页名称")
    private String homeConfigTypeName;

    /** 备注 */
    @Excel(name = "备注")
    private String configTypeDesc;

    /** 图标地址 */
    @Excel(name = "图标地址")
    private String configTypeIcon;

    /** 首页图片地址 */
    @Excel(name = "首页图片地址")
    private String homeConfigTypePic;

    private Long parentId;

    private String ancestors;

    private List<HwProductCaseInfo> hwProductCaseInfoList;

    /** 子类型 */
    private List<HwPortalConfigType> children = new ArrayList<HwPortalConfigType>();

    public void setConfigTypeId(Long configTypeId) 
    {
        this.configTypeId = configTypeId;
    }

    public Long getConfigTypeId() 
    {
        return configTypeId;
    }
    public void setConfigTypeClassfication(String configTypeClassfication) 
    {
        this.configTypeClassfication = configTypeClassfication;
    }

    public String getConfigTypeClassfication() 
    {
        return configTypeClassfication;
    }
    public void setConfigTypeName(String configTypeName) 
    {
        this.configTypeName = configTypeName;
    }

    public String getConfigTypeName() 
    {
        return configTypeName;
    }
    public void setHomeConfigTypeName(String homeConfigTypeName) 
    {
        this.homeConfigTypeName = homeConfigTypeName;
    }

    public String getHomeConfigTypeName() 
    {
        return homeConfigTypeName;
    }
    public void setConfigTypeDesc(String configTypeDesc) 
    {
        this.configTypeDesc = configTypeDesc;
    }

    public String getConfigTypeDesc() 
    {
        return configTypeDesc;
    }
    public void setConfigTypeIcon(String configTypeIcon) 
    {
        this.configTypeIcon = configTypeIcon;
    }

    public String getConfigTypeIcon() 
    {
        return configTypeIcon;
    }
    public void setHomeConfigTypePic(String homeConfigTypePic) 
    {
        this.homeConfigTypePic = homeConfigTypePic;
    }

    public String getHomeConfigTypePic() 
    {
        return homeConfigTypePic;
    }

    public Long getParentId() {
        return parentId;
    }

    public void setParentId(Long parentId) {
        this.parentId = parentId;
    }

    public String getAncestors() {
        return ancestors;
    }

    public void setAncestors(String ancestors) {
        this.ancestors = ancestors;
    }

    public List<HwProductCaseInfo> getHwProductCaseInfoList() {
        return hwProductCaseInfoList;
    }

    public void setHwProductCaseInfoList(List<HwProductCaseInfo> hwProductCaseInfoList) {
        this.hwProductCaseInfoList = hwProductCaseInfoList;
    }

    public List<HwPortalConfigType> getChildren() {
        return children;
    }

    public void setChildren(List<HwPortalConfigType> children) {
        this.children = children;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("configTypeId", getConfigTypeId())
            .append("configTypeClassfication", getConfigTypeClassfication())
            .append("configTypeName", getConfigTypeName())
            .append("homeConfigTypeName", getHomeConfigTypeName())
            .append("configTypeDesc", getConfigTypeDesc())
            .append("configTypeIcon", getConfigTypeIcon())
            .append("homeConfigTypePic", getHomeConfigTypePic())
            .append("parentId", getParentId())
            .append("ancestors", getAncestors())
            .append("createTime", getCreateTime())
            .append("createBy", getCreateBy())
            .append("updateTime", getUpdateTime())
            .append("updateBy", getUpdateBy())
            .toString();
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/HwProductCaseInfo.java

package com.ruoyi.portal.domain;

import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

/**
 * 案例内容对象 hw_product_case_info
 * 
 * @author xins
 * @date 2024-12-01
 */
public class HwProductCaseInfo extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    /** 主键标识 */
    private Long caseInfoId;

    /** 案例标题 */
    @Excel(name = "案例标题")
    private String caseInfoTitle;

    /** 配置类型ID */
    @Excel(name = "配置类型ID")
    private Long configTypeId;

    /** 典型案例标识(1是0否) */
    @Excel(name = "典型案例标识(1是0否)")
    private String typicalFlag;

    /** 案例内容 */
    @Excel(name = "案例内容")
    private String caseInfoDesc;

    /** 案例内容图片 */
    @Excel(name = "案例内容图片")
    private String caseInfoPic;

    /** 案例详情 */
    @Excel(name = "案例详情")
    private String caseInfoHtml;

    private String homeTypicalFlag;


    public void setCaseInfoId(Long caseInfoId) 
    {
        this.caseInfoId = caseInfoId;
    }

    public Long getCaseInfoId() 
    {
        return caseInfoId;
    }
    public void setCaseInfoTitle(String caseInfoTitle) 
    {
        this.caseInfoTitle = caseInfoTitle;
    }

    public String getCaseInfoTitle() 
    {
        return caseInfoTitle;
    }

    public Long getConfigTypeId() {
        return configTypeId;
    }

    public void setConfigTypeId(Long configTypeId) {
        this.configTypeId = configTypeId;
    }

    public void setTypicalFlag(String typicalFlag)
    {
        this.typicalFlag = typicalFlag;
    }

    public String getTypicalFlag() 
    {
        return typicalFlag;
    }
    public void setCaseInfoDesc(String caseInfoDesc) 
    {
        this.caseInfoDesc = caseInfoDesc;
    }

    public String getCaseInfoDesc() 
    {
        return caseInfoDesc;
    }
    public void setCaseInfoPic(String caseInfoPic) 
    {
        this.caseInfoPic = caseInfoPic;
    }

    public String getCaseInfoPic() 
    {
        return caseInfoPic;
    }
    public void setCaseInfoHtml(String caseInfoHtml) 
    {
        this.caseInfoHtml = caseInfoHtml;
    }

    public String getCaseInfoHtml() 
    {
        return caseInfoHtml;
    }

    public String getHomeTypicalFlag() {
        return homeTypicalFlag;
    }

    public void setHomeTypicalFlag(String homeTypicalFlag) {
        this.homeTypicalFlag = homeTypicalFlag;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("caseInfoId", getCaseInfoId())
            .append("caseInfoTitle", getCaseInfoTitle())
            .append("configTypeId", getConfigTypeId())
            .append("typicalFlag", getTypicalFlag())
            .append("caseInfoDesc", getCaseInfoDesc())
            .append("caseInfoPic", getCaseInfoPic())
            .append("caseInfoHtml", getCaseInfoHtml())
            .append("createTime", getCreateTime())
            .append("createBy", getCreateBy())
            .append("updateTime", getUpdateTime())
            .append("updateBy", getUpdateBy())
            .toString();
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/HwProductInfo.java

package com.ruoyi.portal.domain;

import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import java.util.List;

/**
 * 产品信息配置对象 hw_product_info
 * 
 * @author xins
 * @date 2024-12-01
 */
public class HwProductInfo extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    /** 主键标识 */
    private Long productInfoId;

    /** 配置类型(例如物联网解决方案下的物联网平台和物联网硬件产品系列) */
    @Excel(name = "配置类型", readConverterExp = "例=如物联网解决方案下的物联网平台和物联网硬件产品系列")
    private String configTypeId;

    /** 是否按tab显示1是0否 */
    @Excel(name = "是否按tab显示", readConverterExp = "1=是0否")
    private String tabFlag;

    /** 配置模式(1图标 +文字+内容横铺4个2左标题+内容右图片3左图标右标题+内容一行2个4左大图右标题+内容一行2个5上标题+下图片6上标题+内容下图片7图标标题内容一行3个,8左图右图9上图下内容一行4个) */
    @Excel(name = "配置模式(1图标 +文字+内容横铺4个2左标题+内容右图片3左图标右标题+内容一行2个4左大图右标题+内容一行2个5上标题+下图片6上标题+内容下图片7图标标题内容一行3个,8左图右图9上图下内容一行4个)13为hw官网配置模式")
    private String configModal;

    /** 英文标题 */
    @Excel(name = "英文标题")
    private String productInfoEtitle;

    /** 中文标题 */
    @Excel(name = "中文标题")
    private String productInfoCtitle;

    /** 顺序 */
    @Excel(name = "顺序")
    private Long productInfoOrder;

    /** 产品信息明细配置信息 */
    private List<HwProductInfoDetail> hwProductInfoDetailList;

    private Long parentId;

    private String configTypeName;
    public void setProductInfoId(Long productInfoId) 
    {
        this.productInfoId = productInfoId;
    }

    public Long getProductInfoId() 
    {
        return productInfoId;
    }
    public void setConfigTypeId(String configTypeId) 
    {
        this.configTypeId = configTypeId;
    }

    public String getConfigTypeId() 
    {
        return configTypeId;
    }
    public void setTabFlag(String tabFlag) 
    {
        this.tabFlag = tabFlag;
    }

    public String getTabFlag() 
    {
        return tabFlag;
    }
    public void setConfigModal(String configModal) 
    {
        this.configModal = configModal;
    }

    public String getConfigModal() 
    {
        return configModal;
    }
    public void setProductInfoEtitle(String productInfoEtitle)
    {
        this.productInfoEtitle = productInfoEtitle;
    }

    public String getProductInfoEtitle()
    {
        return productInfoEtitle;
    }
    public void setProductInfoCtitle(String productInfoCtitle) 
    {
        this.productInfoCtitle = productInfoCtitle;
    }

    public String getProductInfoCtitle() 
    {
        return productInfoCtitle;
    }
    public void setProductInfoOrder(Long productInfoOrder) 
    {
        this.productInfoOrder = productInfoOrder;
    }

    public Long getProductInfoOrder() 
    {
        return productInfoOrder;
    }

    public List<HwProductInfoDetail> getHwProductInfoDetailList()
    {
        return hwProductInfoDetailList;
    }

    public void setHwProductInfoDetailList(List<HwProductInfoDetail> hwProductInfoDetailList)
    {
        this.hwProductInfoDetailList = hwProductInfoDetailList;
    }

    public Long getParentId() {
        return parentId;
    }

    public void setParentId(Long parentId) {
        this.parentId = parentId;
    }

    public String getConfigTypeName() {
        return configTypeName;
    }

    public void setConfigTypeName(String configTypeName) {
        this.configTypeName = configTypeName;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
                .append("productInfoId", getProductInfoId())
                .append("configTypeId", getConfigTypeId())
                .append("tabFlag", getTabFlag())
                .append("configModal", getConfigModal())
                .append("productInfoEtitle", getProductInfoEtitle())
                .append("productInfoCtitle", getProductInfoCtitle())
                .append("productInfoOrder", getProductInfoOrder())
                .append("createTime", getCreateTime())
                .append("createBy", getCreateBy())
                .append("updateTime", getUpdateTime())
                .append("updateBy", getUpdateBy())
                .append("hwProductInfoDetailList", getHwProductInfoDetailList())
                .toString();
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/HwProductInfoDetail.java

package com.ruoyi.portal.domain;

import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.TreeEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import java.util.List;


/**
 * 产品信息明细配置对象 hw_product_info_detail
 * 
 * @author xins
 * @date 2024-12-11
 */
public class HwProductInfoDetail extends TreeEntity
{
    private static final long serialVersionUID = 1L;

    /** 主键标识 */
    private Long productInfoDetailId;

    /** 产品信息配置ID */
    @Excel(name = "产品信息配置ID")
    private Long productInfoId;

    /** 配置模式(1图标 +文字+内容横铺4个2左标题+内容右图片3左图标右标题+内容一行2个4左大图右标题+内容一行2个5上标题+下图片6上标题+内容下图片7图标标题内容一行3个,8一张图9上图下内容一行4个);针对右children时配置的 */
    @Excel(name = "配置模式(1图标 +文字+内容横铺4个2左标题+内容右图片3左图标右标题+内容一行2个4左大图右标题+内容一行2个5上标题+下图片6上标题+内容下图片7图标标题内容一行3个,8一张图9上图下内容一行4个);针对右children时配置的")
    private String configModal;

    /** 配置模式(1图标 +文字+内容横铺4个2左标题+内容右图片3左图标右标题+内容一行2个4左大图右标题+内容一行2个5上标题+下图片6上标题+内容下图片7图标标题内容一行3个,8一张图9上图下内容一行4个);针对右children时配置的 */
    @Excel(name = "配置模式(1图标 +文字+内容横铺4个2左标题+内容右图片3左图标右标题+内容一行2个4左大图右标题+内容一行2个5上标题+下图片6上标题+内容下图片7图标标题内容一行3个,8一张图9上图下内容一行4个);针对右children时配置的")
    private String configModel;

    /** 标题 */
    @Excel(name = "标题")
    private String productInfoDetailTitle;

    /** 内容 */
    @Excel(name = "内容")
    private String productInfoDetailDesc;

    /** 顺序 */
    @Excel(name = "顺序")
    private Long productInfoDetailOrder;

    /** 图片地址 */
    @Excel(name = "图片地址")
    private String productInfoDetailPic;

        /** 产品信息明细配置信息 */
        private List<HwProductInfoDetail> hwProductInfoDetailList;

    public void setProductInfoDetailId(Long productInfoDetailId) 
    {
        this.productInfoDetailId = productInfoDetailId;
    }

    public Long getProductInfoDetailId() 
    {
        return productInfoDetailId;
    }
    public void setProductInfoId(Long productInfoId) 
    {
        this.productInfoId = productInfoId;
    }

    public Long getProductInfoId() 
    {
        return productInfoId;
    }
    public void setConfigModal(String configModal) 
    {
        this.configModal = configModal;
    }

    public String getConfigModal() 
    {
        return configModal;
    }
    public void setProductInfoDetailTitle(String productInfoDetailTitle) 
    {
        this.productInfoDetailTitle = productInfoDetailTitle;
    }

    public String getProductInfoDetailTitle() 
    {
        return productInfoDetailTitle;
    }
    public void setProductInfoDetailDesc(String productInfoDetailDesc) 
    {
        this.productInfoDetailDesc = productInfoDetailDesc;
    }

    public String getProductInfoDetailDesc() 
    {
        return productInfoDetailDesc;
    }
    public void setProductInfoDetailOrder(Long productInfoDetailOrder) 
    {
        this.productInfoDetailOrder = productInfoDetailOrder;
    }

    public Long getProductInfoDetailOrder() 
    {
        return productInfoDetailOrder;
    }
    public void setProductInfoDetailPic(String productInfoDetailPic) 
    {
        this.productInfoDetailPic = productInfoDetailPic;
    }

    public String getProductInfoDetailPic() 
    {
        return productInfoDetailPic;
    }

    public List<HwProductInfoDetail> getHwProductInfoDetailList() {
        return hwProductInfoDetailList;
    }

    public void setHwProductInfoDetailList(List<HwProductInfoDetail> hwProductInfoDetailList) {
        this.hwProductInfoDetailList = hwProductInfoDetailList;
    }

    public String getConfigModel() {
        return configModel;
    }

    public void setConfigModel(String configModel) {
        this.configModel = configModel;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("productInfoDetailId", getProductInfoDetailId())
            .append("parentId", getParentId())
            .append("productInfoId", getProductInfoId())
            .append("configModal", getConfigModal())
            .append("productInfoDetailTitle", getProductInfoDetailTitle())
            .append("productInfoDetailDesc", getProductInfoDetailDesc())
            .append("productInfoDetailOrder", getProductInfoDetailOrder())
            .append("productInfoDetailPic", getProductInfoDetailPic())
            .append("ancestors", getAncestors())
            .append("createTime", getCreateTime())
            .append("createBy", getCreateBy())
            .append("updateTime", getUpdateTime())
            .append("updateBy", getUpdateBy())
            .toString();
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/HwWeb.java

package com.ruoyi.portal.domain;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;

/**
 * haiwei官网json对象 hw_web
 *
 * @author ruoyi
 * @date 2025-08-18
 */
public class HwWeb extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    /** 主键 */
    private Long webId;

    /** json */
    @Excel(name = "json")
    private String webJson;

    /** json字符串 */
    @Excel(name = "json字符串")
    private String webJsonString;

    /** 页面 */
    @Excel(name = "页面")
    private Long webCode;

    /** 逻辑删除标志:'0'未删除,'1'已删除 */
    private String isDelete;

    /** json字符串 */
    @Excel(name = "字符串")
    private String webJsonEnglish;

    public void setWebId(Long webId)
    {
        this.webId = webId;
    }

    public Long getWebId()
    {
        return webId;
    }
    public void setWebJson(String webJson)
    {
        this.webJson = webJson;
    }

    public String getWebJson()
    {
        return webJson;
    }
    public void setWebJsonString(String webJsonString)
    {
        this.webJsonString = webJsonString;
    }

    public String getWebJsonString()
    {
        return webJsonString;
    }
    public void setWebCode(Long webCode)
    {
        this.webCode = webCode;
    }

    public Long getWebCode()
    {
        return webCode;
    }

    public String getIsDelete() {
        return isDelete;
    }

    public void setIsDelete(String isDelete) {
        this.isDelete = isDelete;
    }

    public String getwebJsonEnglish() {
        return webJsonEnglish;
    }

    public void setwebJsonEnglish(String webJsonEnglish) {
        this.webJsonEnglish = webJsonEnglish;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
                .append("webId", getWebId())
                .append("webJson", getWebJson())
                .append("webJsonString", getWebJsonString())
                .append("webCode", getWebCode())
                .append("isDelete", getIsDelete())
                .append("webJsonEnglish", getwebJsonEnglish())
                .toString();
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/HwWeb1.java

package com.ruoyi.portal.domain;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;

/**
 * haiwei官网json对象 hw_web1
 *
 * @author ruoyi
 * @date 2025-08-18
 */
public class HwWeb1 extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    /** 主键 */
    private Long webId;

    /** json */
    @Excel(name = "json")
    private String webJson;

    /** json字符串 */
    @Excel(name = "json字符串")
    private String webJsonString;

    /** 页面 */
    @Excel(name = "页面")
    private Long webCode;

    private Long deviceId;

    private Long typeId;

    /** 逻辑删除标志:'0'未删除,'1'已删除 */
    private String isDelete;

    /** json字符串 */
    @Excel(name = "字符串")
    private String webJsonEnglish;

    public void setWebId(Long webId)
    {
        this.webId = webId;
    }

    public Long getWebId()
    {
        return webId;
    }
    public void setWebJson(String webJson)
    {
        this.webJson = webJson;
    }

    public String getWebJson()
    {
        return webJson;
    }
    public void setWebJsonString(String webJsonString)
    {
        this.webJsonString = webJsonString;
    }

    public String getWebJsonString()
    {
        return webJsonString;
    }
    public void setWebCode(Long webCode)
    {
        this.webCode = webCode;
    }

    public Long getWebCode()
    {
        return webCode;
    }

    public Long getDeviceId() {
        return deviceId;
    }

    public void setDeviceId(Long deviceId) {
        this.deviceId = deviceId;
    }

    public Long getTypeId() {
        return typeId;
    }

    public void setTypeId(Long typeId) {
        this.typeId = typeId;
    }

    public String getIsDelete() {
        return isDelete;
    }

    public void setIsDelete(String isDelete) {
        this.isDelete = isDelete;
    }

    public String getwebJsonEnglish() {
        return webJsonEnglish;
    }

    public void setwebJsonEnglish(String webJsonEnglish) {
        this.webJsonEnglish = webJsonEnglish;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
                .append("webId", getWebId())
                .append("webJson", getWebJson())
                .append("webJsonString", getWebJsonString())
                .append("webCode", getWebCode())
                .append("deviceId", getDeviceId())
                .append("typeId", getTypeId())
                .append("isDelete", getIsDelete())
                .append("webJsonEnglish", getwebJsonEnglish())
                .toString();
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/HwWebDocument.java

package com.ruoyi.portal.domain;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import com.fasterxml.jackson.annotation.JsonProperty;

/**
 * Hw资料文件对象 hw_web_document
 * 
 * @author zch
 * @date 2025-09-22
 */
public class HwWebDocument extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    /** 主键 */
    private String documentId;

    /** 租户id */
    @Excel(name = "租户id")
    private Long tenantId;

    /** 文件存储地址 */
    @Excel(name = "文件存储地址")
    private String documentAddress;

    /** 页面编码,用来连表查询 */
    @Excel(name = "页面编码,用来连表查询")
    private String webCode;

    /** 密钥 */
    // @Excel(name = "密钥")
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private String secretKey;

    /** json */
    private String json;

    /** 文件类型 */
    private String type;

    /** 逻辑删除标志:'0'未删除,'1'已删除 */
    private String isDelete;

    public void setDocumentId(String documentId) 
    {
        this.documentId = documentId;
    }

    public String getDocumentId()
    {
        return documentId;
    }
    public void setTenantId(Long tenantId) 
    {
        this.tenantId = tenantId;
    }

    public Long getTenantId() 
    {
        return tenantId;
    }
    public void setDocumentAddress(String documentAddress) 
    {
        this.documentAddress = documentAddress;
    }

    public String getDocumentAddress() 
    {
        return documentAddress;
    }
    public void setWebCode(String webCode) 
    {
        this.webCode = webCode;
    }

    public String getWebCode() 
    {
        return webCode;
    }
    public void setSecretKey(String secretKey) 
    {
        this.secretKey = secretKey;
    }

    public String getSecretKey() 
    {
        return secretKey;
    }

    public boolean getHasSecret() {
        return secretKey != null && !secretKey.trim().isEmpty();
    }

    public String getJson() {
        return json;
    }

    public void setJson(String json) {
        this.json = json;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getIsDelete() {
        return isDelete;
    }

    public void setIsDelete(String isDelete) {
        this.isDelete = isDelete;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("documentId", getDocumentId())
            .append("tenantId", getTenantId())
            .append("documentAddress", getDocumentAddress())
            .append("createTime", getCreateTime())
            .append("webCode", getWebCode())
            .append("hasSecret", getHasSecret())
            .append("json", getJson())
            .append("type", getType())
            .append("isDelete", getIsDelete())
            .toString();
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/HwWebMenu.java

package com.ruoyi.portal.domain;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.TreeEntity;

/**
 * haiwei官网菜单对象 hw_web_menu
 *
 * @author zch
 * @date 2025-08-18
 */
public class HwWebMenu extends TreeEntity
{
    private static final long serialVersionUID = 1L;

    /** 菜单主键id */
    private Long webMenuId;

    /** 父节点 */
    @Excel(name = "父节点")
    private Long parent;

    /** 状态 */
    @Excel(name = "状态")
    private String status;

    /** 菜单名称 */
    @Excel(name = "菜单名称")
    private String webMenuName;

    /** 租户 */
    @Excel(name = "租户")
    private Long tenantId;

    /** 图片地址 */
    @Excel(name = "图片地址")
    private String webMenuPic;

    /** 官网菜单类型 */
    @Excel(name = "官网菜单类型")
    private Long webMenuType;

    /** 排序 */
    @Excel(name = "排序")
    private Integer order;

    /** 逻辑删除标志:'0'未删除,'1'已删除 */
    private String isDelete;

    private String webMenuNameEnglish;

    public void setWebMenuId(Long webMenuId)
    {
        this.webMenuId = webMenuId;
    }

    public Long getWebMenuId()
    {
        return webMenuId;
    }
    public void setParent(Long parent)
    {
        this.parent = parent;
    }

    public Long getParent()
    {
        return parent;
    }
    public void setStatus(String status)
    {
        this.status = status;
    }

    public String getStatus()
    {
        return status;
    }
    public void setWebMenuName(String webMenuName)
    {
        this.webMenuName = webMenuName;
    }

    public String getWebMenuName()
    {
        return webMenuName;
    }
    public void setTenantId(Long tenantId)
    {
        this.tenantId = tenantId;
    }

    public Long getTenantId()
    {
        return tenantId;
    }
    public void setWebMenuPic(String webMenuPic)
    {
        this.webMenuPic = webMenuPic;
    }

    public String getWebMenuPic()
    {
        return webMenuPic;
    }
    public void setWebMenuType(Long webMenuType)
    {
        this.webMenuType = webMenuType;
    }

    public Long getWebMenuType()
    {
        return webMenuType;
    }

    public Integer getOrder() {
        return order;
    }

    public void setOrder(Integer order) {
        this.order = order;
    }

    public String getIsDelete() {
        return isDelete;
    }

    public void setIsDelete(String isDelete) {
        this.isDelete = isDelete;
    }

    public String getWebMenuNameEnglish() {
        return webMenuNameEnglish;
    }

    public void setWebMenuNameEnglish(String webMenuNameEnglish) {
        this.webMenuNameEnglish = webMenuNameEnglish;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
                .append("webMenuId", getWebMenuId())
                .append("parent", getParent())
                .append("ancestors", getAncestors())
                .append("status", getStatus())
                .append("webMenuName", getWebMenuName())
                .append("tenantId", getTenantId())
                .append("webMenuPic", getWebMenuPic())
                .append("webMenuType", getWebMenuType())
                .append("order", getOrder())
                .append("isDelete", getIsDelete())
                .append("webMenuNameEnglish", getWebMenuNameEnglish())
                .toString();
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/HwWebMenu1.java

package com.ruoyi.portal.domain;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.TreeEntity;

import java.util.List;

/**
 * haiwei官网菜单对象 hw_web_menu1
 *
 * @author zch
 * @date 2025-08-18
 */
public class HwWebMenu1 extends TreeEntity
{
    private static final long serialVersionUID = 1L;

    /** 菜单主键id */
    private Long webMenuId;

    /** 父节点 */
    @Excel(name = "父节点")
    private Long parent;

    /** 状态 */
    @Excel(name = "状态")
    private String status;

    /** 菜单名称 */
    @Excel(name = "菜单名称")
    private String webMenuName;

    /** 租户 */
    @Excel(name = "租户")
    private Long tenantId;

    /** 图片地址 */
    @Excel(name = "图片地址")
    private String webMenuPic;

    /** 官网菜单类型 */
    @Excel(name = "官网菜单类型")
    private Long webMenuType;

    private String valuel;

    /** 逻辑删除标志:'0'未删除,'1'已删除 */
    private String isDelete;

    private String webMenuNameEnglish;

    public void setWebMenuId(Long webMenuId)
    {
        this.webMenuId = webMenuId;
    }

    public Long getWebMenuId()
    {
        return webMenuId;
    }
    public void setParent(Long parent)
    {
        this.parent = parent;
    }

    public Long getParent()
    {
        return parent;
    }
    public void setStatus(String status)
    {
        this.status = status;
    }

    public String getStatus()
    {
        return status;
    }
    public void setWebMenuName(String webMenuName)
    {
        this.webMenuName = webMenuName;
    }

    public String getWebMenuName()
    {
        return webMenuName;
    }
    public void setTenantId(Long tenantId)
    {
        this.tenantId = tenantId;
    }

    public Long getTenantId()
    {
        return tenantId;
    }
    public void setWebMenuPic(String webMenuPic)
    {
        this.webMenuPic = webMenuPic;
    }

    public String getWebMenuPic()
    {
        return webMenuPic;
    }
    public void setWebMenuType(Long webMenuType)
    {
        this.webMenuType = webMenuType;
    }

    public Long getWebMenuType()
    {
        return webMenuType;
    }

    public String getValuel() {
        return valuel;
    }
    public void setValuel(String valuel) {
        this.valuel = valuel;
    }

    public String getIsDelete() {
        return isDelete;
    }

    public void setIsDelete(String isDelete) {
        this.isDelete = isDelete;
    }

    public String getWebMenuNameEnglish() {
        return webMenuNameEnglish;
    }

    public void setWebMenuNameEnglish(String webMenuNameEnglish) {
        this.webMenuNameEnglish = webMenuNameEnglish;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
                .append("webMenuId", getWebMenuId())
                .append("parent", getParent())
                .append("ancestors", getAncestors())
                .append("status", getStatus())
                .append("webMenuName", getWebMenuName())
                .append("tenantId", getTenantId())
                .append("webMenuPic", getWebMenuPic())
                .append("webMenuType", getWebMenuType())
                .append("valuel", getValuel())
                .append("isDelete", getIsDelete())
                .append("webMenuNameEnglish", getWebMenuNameEnglish())
                .toString();
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/HwWebVisitDaily.java

package com.ruoyi.portal.domain;

import java.util.Date;

/**
 * 官网访问日汇总
 *
 * @author ruoyi
 */
public class HwWebVisitDaily
{
    private Date statDate;

    private Long pv;

    private Long uv;

    private Long ipUv;

    private Long avgStayMs;

    private Double bounceRate;

    private Long searchCount;

    private Long downloadCount;

    private Date createdAt;

    private Date updatedAt;

    public Date getStatDate()
    {
        return statDate;
    }

    public void setStatDate(Date statDate)
    {
        this.statDate = statDate;
    }

    public Long getPv()
    {
        return pv;
    }

    public void setPv(Long pv)
    {
        this.pv = pv;
    }

    public Long getUv()
    {
        return uv;
    }

    public void setUv(Long uv)
    {
        this.uv = uv;
    }

    public Long getIpUv()
    {
        return ipUv;
    }

    public void setIpUv(Long ipUv)
    {
        this.ipUv = ipUv;
    }

    public Long getAvgStayMs()
    {
        return avgStayMs;
    }

    public void setAvgStayMs(Long avgStayMs)
    {
        this.avgStayMs = avgStayMs;
    }

    public Double getBounceRate()
    {
        return bounceRate;
    }

    public void setBounceRate(Double bounceRate)
    {
        this.bounceRate = bounceRate;
    }

    public Long getSearchCount()
    {
        return searchCount;
    }

    public void setSearchCount(Long searchCount)
    {
        this.searchCount = searchCount;
    }

    public Long getDownloadCount()
    {
        return downloadCount;
    }

    public void setDownloadCount(Long downloadCount)
    {
        this.downloadCount = downloadCount;
    }

    public Date getCreatedAt()
    {
        return createdAt;
    }

    public void setCreatedAt(Date createdAt)
    {
        this.createdAt = createdAt;
    }

    public Date getUpdatedAt()
    {
        return updatedAt;
    }

    public void setUpdatedAt(Date updatedAt)
    {
        this.updatedAt = updatedAt;
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/HwWebVisitEvent.java

package com.ruoyi.portal.domain;

import com.ruoyi.common.core.domain.BaseEntity;

import java.util.Date;

/**
 * 官网匿名访问事件明细
 *
 * @author ruoyi
 */
public class HwWebVisitEvent extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    private Long id;

    private String eventType;

    private String visitorId;

    private String sessionId;

    private String path;

    private String referrer;

    private String utmSource;

    private String utmMedium;

    private String utmCampaign;

    private String keyword;

    private String ipHash;

    private String ua;

    private String device;

    private String browser;

    private String os;

    private Long stayMs;

    private Date eventTime;

    private Date createdAt;

    public Long getId()
    {
        return id;
    }

    public void setId(Long id)
    {
        this.id = id;
    }

    public String getEventType()
    {
        return eventType;
    }

    public void setEventType(String eventType)
    {
        this.eventType = eventType;
    }

    public String getVisitorId()
    {
        return visitorId;
    }

    public void setVisitorId(String visitorId)
    {
        this.visitorId = visitorId;
    }

    public String getSessionId()
    {
        return sessionId;
    }

    public void setSessionId(String sessionId)
    {
        this.sessionId = sessionId;
    }

    public String getPath()
    {
        return path;
    }

    public void setPath(String path)
    {
        this.path = path;
    }

    public String getReferrer()
    {
        return referrer;
    }

    public void setReferrer(String referrer)
    {
        this.referrer = referrer;
    }

    public String getUtmSource()
    {
        return utmSource;
    }

    public void setUtmSource(String utmSource)
    {
        this.utmSource = utmSource;
    }

    public String getUtmMedium()
    {
        return utmMedium;
    }

    public void setUtmMedium(String utmMedium)
    {
        this.utmMedium = utmMedium;
    }

    public String getUtmCampaign()
    {
        return utmCampaign;
    }

    public void setUtmCampaign(String utmCampaign)
    {
        this.utmCampaign = utmCampaign;
    }

    public String getKeyword()
    {
        return keyword;
    }

    public void setKeyword(String keyword)
    {
        this.keyword = keyword;
    }

    public String getIpHash()
    {
        return ipHash;
    }

    public void setIpHash(String ipHash)
    {
        this.ipHash = ipHash;
    }

    public String getUa()
    {
        return ua;
    }

    public void setUa(String ua)
    {
        this.ua = ua;
    }

    public String getDevice()
    {
        return device;
    }

    public void setDevice(String device)
    {
        this.device = device;
    }

    public String getBrowser()
    {
        return browser;
    }

    public void setBrowser(String browser)
    {
        this.browser = browser;
    }

    public String getOs()
    {
        return os;
    }

    public void setOs(String os)
    {
        this.os = os;
    }

    public Long getStayMs()
    {
        return stayMs;
    }

    public void setStayMs(Long stayMs)
    {
        this.stayMs = stayMs;
    }

    public Date getEventTime()
    {
        return eventTime;
    }

    public void setEventTime(Date eventTime)
    {
        this.eventTime = eventTime;
    }

    public Date getCreatedAt()
    {
        return createdAt;
    }

    public void setCreatedAt(Date createdAt)
    {
        this.createdAt = createdAt;
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/SecureDocumentRequest.java

package com.ruoyi.portal.domain;

public class SecureDocumentRequest
{
    private String documentId;
    private String providedKey;

    public String getDocumentId()
    {
        return documentId;
    }

    public void setDocumentId(String documentId)
    {
        this.documentId = documentId;
    }

    public String getProvidedKey()
    {
        return providedKey;
    }

    public void setProvidedKey(String providedKey)
    {
        this.providedKey = providedKey;
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/domain/vo/TreeSelect.java

package com.ruoyi.portal.domain.vo;

import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.ruoyi.portal.domain.HwPortalConfigType;

/**
 * Treeselect树结构实体类
 * 
 * @author ruoyi
 */
public class TreeSelect implements Serializable
{
    private static final long serialVersionUID = 1L;

    /** 节点ID */
    private Long id;

    /** 节点名称 */
    private String label;

    /** 子节点 */
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    private List<TreeSelect> children;

    public TreeSelect()
    {

    }

    public TreeSelect(HwPortalConfigType portalConfigType)
    {
        this.id = portalConfigType.getConfigTypeId();
        this.label = portalConfigType.getConfigTypeName();
        this.children = portalConfigType.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    public Long getId()
    {
        return id;
    }

    public void setId(Long id)
    {
        this.id = id;
    }

    public String getLabel()
    {
        return label;
    }

    public void setLabel(String label)
    {
        this.label = label;
    }

    public List<TreeSelect> getChildren()
    {
        return children;
    }

    public void setChildren(List<TreeSelect> children)
    {
        this.children = children;
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/mapper/HwAboutUsInfoDetailMapper.java

package com.ruoyi.portal.mapper;

import com.ruoyi.portal.domain.HwAboutUsInfoDetail;

import java.util.List;

/**
 * 关于我们信息明细Mapper接口
 * 
 * @author ruoyi
 * @date 2024-12-01
 */
public interface HwAboutUsInfoDetailMapper 
{
    /**
     * 查询关于我们信息明细
     * 
     * @param usInfoDetailId 关于我们信息明细主键
     * @return 关于我们信息明细
     */
    public HwAboutUsInfoDetail selectHwAboutUsInfoDetailByUsInfoDetailId(Long usInfoDetailId);

    /**
     * 查询关于我们信息明细列表
     * 
     * @param hwAboutUsInfoDetail 关于我们信息明细
     * @return 关于我们信息明细集合
     */
    public List<HwAboutUsInfoDetail> selectHwAboutUsInfoDetailList(HwAboutUsInfoDetail hwAboutUsInfoDetail);

    /**
     * 新增关于我们信息明细
     * 
     * @param hwAboutUsInfoDetail 关于我们信息明细
     * @return 结果
     */
    public int insertHwAboutUsInfoDetail(HwAboutUsInfoDetail hwAboutUsInfoDetail);

    /**
     * 修改关于我们信息明细
     * 
     * @param hwAboutUsInfoDetail 关于我们信息明细
     * @return 结果
     */
    public int updateHwAboutUsInfoDetail(HwAboutUsInfoDetail hwAboutUsInfoDetail);

    /**
     * 删除关于我们信息明细
     * 
     * @param usInfoDetailId 关于我们信息明细主键
     * @return 结果
     */
    public int deleteHwAboutUsInfoDetailByUsInfoDetailId(Long usInfoDetailId);

    /**
     * 批量删除关于我们信息明细
     * 
     * @param usInfoDetailIds 需要删除的数据主键集合
     * @return 结果
     */
    public int deleteHwAboutUsInfoDetailByUsInfoDetailIds(Long[] usInfoDetailIds);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/mapper/HwAboutUsInfoMapper.java

package com.ruoyi.portal.mapper;

import com.ruoyi.portal.domain.HwAboutUsInfo;

import java.util.List;

/**
 * 关于我们信息Mapper接口
 * 
 * @author xins
 * @date 2024-12-01
 */
public interface HwAboutUsInfoMapper 
{
    /**
     * 查询关于我们信息
     * 
     * @param aboutUsInfoId 关于我们信息主键
     * @return 关于我们信息
     */
    public HwAboutUsInfo selectHwAboutUsInfoByAboutUsInfoId(Long aboutUsInfoId);

    /**
     * 查询关于我们信息列表
     * 
     * @param hwAboutUsInfo 关于我们信息
     * @return 关于我们信息集合
     */
    public List<HwAboutUsInfo> selectHwAboutUsInfoList(HwAboutUsInfo hwAboutUsInfo);

    /**
     * 新增关于我们信息
     * 
     * @param hwAboutUsInfo 关于我们信息
     * @return 结果
     */
    public int insertHwAboutUsInfo(HwAboutUsInfo hwAboutUsInfo);

    /**
     * 修改关于我们信息
     * 
     * @param hwAboutUsInfo 关于我们信息
     * @return 结果
     */
    public int updateHwAboutUsInfo(HwAboutUsInfo hwAboutUsInfo);

    /**
     * 删除关于我们信息
     * 
     * @param aboutUsInfoId 关于我们信息主键
     * @return 结果
     */
    public int deleteHwAboutUsInfoByAboutUsInfoId(Long aboutUsInfoId);

    /**
     * 批量删除关于我们信息
     * 
     * @param aboutUsInfoIds 需要删除的数据主键集合
     * @return 结果
     */
    public int deleteHwAboutUsInfoByAboutUsInfoIds(Long[] aboutUsInfoIds);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/mapper/HwAnalyticsMapper.java

package com.ruoyi.portal.mapper;

import com.ruoyi.portal.domain.HwWebVisitDaily;
import com.ruoyi.portal.domain.HwWebVisitEvent;
import com.ruoyi.portal.domain.dto.AnalyticsRankItemDTO;
import org.apache.ibatis.annotations.Param;

import java.time.LocalDate;
import java.util.List;

/**
 * 官网访问监控 Mapper
 *
 * @author ruoyi
 */
public interface HwAnalyticsMapper
{
    /**
     * 新增访问事件
     *
     * @param event 事件
     * @return 结果
     */
    int insertVisitEvent(HwWebVisitEvent event);

    /**
     * 查询指定日期事件总数
     *
     * @param statDate 日期
     * @param eventType 事件类型
     * @return 数量
     */
    Long countEventByType(@Param("statDate") LocalDate statDate, @Param("eventType") String eventType);

    /**
     * 查询指定日期访客 UV
     *
     * @param statDate 日期
     * @return UV
     */
    Long countDistinctVisitor(@Param("statDate") LocalDate statDate);

    /**
     * 查询指定日期 IP UV
     *
     * @param statDate 日期
     * @return IP UV
     */
    Long countDistinctIp(@Param("statDate") LocalDate statDate);

    /**
     * 查询指定日期平均停留时长
     *
     * @param statDate 日期
     * @return 平均停留时长
     */
    Long avgStayMs(@Param("statDate") LocalDate statDate);

    /**
     * 查询指定日期会话总数
     *
     * @param statDate 日期
     * @return 会话总数
     */
    Long countDistinctSessions(@Param("statDate") LocalDate statDate);

    /**
     * 查询仅访问一个页面的会话总数
     *
     * @param statDate 日期
     * @return 会话总数
     */
    Long countSinglePageSessions(@Param("statDate") LocalDate statDate);

    /**
     * 查询入口页排行
     *
     * @param statDate 日期
     * @param limit 结果数量
     * @return 排行
     */
    List<AnalyticsRankItemDTO> selectTopEntryPages(@Param("statDate") LocalDate statDate, @Param("limit") int limit);

    /**
     * 查询热门页面排行
     *
     * @param statDate 日期
     * @param limit 结果数量
     * @return 排行
     */
    List<AnalyticsRankItemDTO> selectTopHotPages(@Param("statDate") LocalDate statDate, @Param("limit") int limit);

    /**
     * 查询热门关键词排行
     *
     * @param statDate 日期
     * @param limit 结果数量
     * @return 排行
     */
    List<AnalyticsRankItemDTO> selectTopKeywords(@Param("statDate") LocalDate statDate, @Param("limit") int limit);

    /**
     * 新增或更新日汇总
     *
     * @param daily 日汇总
     * @return 结果
     */
    int upsertDaily(HwWebVisitDaily daily);

    /**
     * 查询日汇总
     *
     * @param statDate 日期
     * @return 日汇总
     */
    HwWebVisitDaily selectDailyByDate(@Param("statDate") LocalDate statDate);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/mapper/HwContactUsInfoMapper.java

package com.ruoyi.portal.mapper;

import com.ruoyi.portal.domain.HwContactUsInfo;

import java.util.List;

/**
 * 联系我们信息Mapper接口
 * 
 * @author xins
 * @date 2024-12-01
 */
public interface HwContactUsInfoMapper 
{
    /**
     * 查询联系我们信息
     * 
     * @param contactUsInfoId 联系我们信息主键
     * @return 联系我们信息
     */
    public HwContactUsInfo selectHwContactUsInfoByContactUsInfoId(Long contactUsInfoId);

    /**
     * 查询联系我们信息列表
     * 
     * @param hwContactUsInfo 联系我们信息
     * @return 联系我们信息集合
     */
    public List<HwContactUsInfo> selectHwContactUsInfoList(HwContactUsInfo hwContactUsInfo);

    /**
     * 新增联系我们信息
     * 
     * @param hwContactUsInfo 联系我们信息
     * @return 结果
     */
    public int insertHwContactUsInfo(HwContactUsInfo hwContactUsInfo);

    /**
     * 修改联系我们信息
     * 
     * @param hwContactUsInfo 联系我们信息
     * @return 结果
     */
    public int updateHwContactUsInfo(HwContactUsInfo hwContactUsInfo);

    /**
     * 删除联系我们信息
     * 
     * @param contactUsInfoId 联系我们信息主键
     * @return 结果
     */
    public int deleteHwContactUsInfoByContactUsInfoId(Long contactUsInfoId);

    /**
     * 批量删除联系我们信息
     * 
     * @param contactUsInfoIds 需要删除的数据主键集合
     * @return 结果
     */
    public int deleteHwContactUsInfoByContactUsInfoIds(Long[] contactUsInfoIds);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/mapper/HwPortalConfigMapper.java

package com.ruoyi.portal.mapper;

import com.ruoyi.portal.domain.HwPortalConfig;

import java.util.List;

/**
 * 门户网站配置Mapper接口
 * 
 * @author xins
 * @date 2024-12-01
 */
public interface HwPortalConfigMapper 
{
    /**
     * 查询门户网站配置
     * 
     * @param portalConfigId 门户网站配置主键
     * @return 门户网站配置
     */
    public HwPortalConfig selectHwPortalConfigByPortalConfigId(Long portalConfigId);

    /**
     * 查询门户网站配置列表
     * 
     * @param hwPortalConfig 门户网站配置
     * @return 门户网站配置集合
     */
    public List<HwPortalConfig> selectHwPortalConfigList(HwPortalConfig hwPortalConfig);

    /**
     * 新增门户网站配置
     * 
     * @param hwPortalConfig 门户网站配置
     * @return 结果
     */
    public int insertHwPortalConfig(HwPortalConfig hwPortalConfig);

    /**
     * 修改门户网站配置
     * 
     * @param hwPortalConfig 门户网站配置
     * @return 结果
     */
    public int updateHwPortalConfig(HwPortalConfig hwPortalConfig);

    /**
     * 删除门户网站配置
     * 
     * @param portalConfigId 门户网站配置主键
     * @return 结果
     */
    public int deleteHwPortalConfigByPortalConfigId(Long portalConfigId);

    /**
     * 批量删除门户网站配置
     * 
     * @param portalConfigIds 需要删除的数据主键集合
     * @return 结果
     */
    public int deleteHwPortalConfigByPortalConfigIds(Long[] portalConfigIds);

    /**
     * 查询门户网站配置列表,join hw_portal_config_type
     *
     * @param hwPortalConfig 门户网站配置
     * @return 门户网站配置集合
     */
    public List<HwPortalConfig> selectHwPortalConfigJoinList(HwPortalConfig hwPortalConfig);


    /**
     * 查询门户网站配置列表
     *
     * @param hwPortalConfig 门户网站配置
     * @return 门户网站配置集合
     */
    public List<HwPortalConfig> selectHwPortalConfigList2(HwPortalConfig hwPortalConfig);


}

ruoyi-portal/src/main/java/com/ruoyi/portal/mapper/HwPortalConfigTypeMapper.java

package com.ruoyi.portal.mapper;

import com.ruoyi.portal.domain.HwPortalConfigType;

import java.util.List;

/**
 * 门户网站配置类型Mapper接口
 * 
 * @author xins
 * @date 2024-12-11
 */
public interface HwPortalConfigTypeMapper 
{
    /**
     * 查询门户网站配置类型
     * 
     * @param configTypeId 门户网站配置类型主键
     * @return 门户网站配置类型
     */
    public HwPortalConfigType selectHwPortalConfigTypeByConfigTypeId(Long configTypeId);

    /**
     * 查询门户网站配置类型列表
     * 
     * @param hwPortalConfigType 门户网站配置类型
     * @return 门户网站配置类型集合
     */
    public List<HwPortalConfigType> selectHwPortalConfigTypeList(HwPortalConfigType hwPortalConfigType);

    /**
     * 新增门户网站配置类型
     * 
     * @param hwPortalConfigType 门户网站配置类型
     * @return 结果
     */
    public int insertHwPortalConfigType(HwPortalConfigType hwPortalConfigType);

    /**
     * 修改门户网站配置类型
     * 
     * @param hwPortalConfigType 门户网站配置类型
     * @return 结果
     */
    public int updateHwPortalConfigType(HwPortalConfigType hwPortalConfigType);

    /**
     * 删除门户网站配置类型
     * 
     * @param configTypeId 门户网站配置类型主键
     * @return 结果
     */
    public int deleteHwPortalConfigTypeByConfigTypeId(Long configTypeId);

    /**
     * 批量删除门户网站配置类型
     * 
     * @param configTypeIds 需要删除的数据主键集合
     * @return 结果
     */
    public int deleteHwPortalConfigTypeByConfigTypeIds(Long[] configTypeIds);


}

ruoyi-portal/src/main/java/com/ruoyi/portal/mapper/HwProductCaseInfoMapper.java

package com.ruoyi.portal.mapper;

import com.ruoyi.portal.domain.HwProductCaseInfo;

import java.util.List;

/**
 * 案例内容Mapper接口
 * 
 * @author xins
 * @date 2024-12-01
 */
public interface HwProductCaseInfoMapper 
{
    /**
     * 查询案例内容
     * 
     * @param caseInfoId 案例内容主键
     * @return 案例内容
     */
    public HwProductCaseInfo selectHwProductCaseInfoByCaseInfoId(Long caseInfoId);

    /**
     * 查询案例内容列表
     * 
     * @param hwProductCaseInfo 案例内容
     * @return 案例内容集合
     */
    public List<HwProductCaseInfo> selectHwProductCaseInfoList(HwProductCaseInfo hwProductCaseInfo);

    /**
     * 新增案例内容
     * 
     * @param hwProductCaseInfo 案例内容
     * @return 结果
     */
    public int insertHwProductCaseInfo(HwProductCaseInfo hwProductCaseInfo);

    /**
     * 修改案例内容
     * 
     * @param hwProductCaseInfo 案例内容
     * @return 结果
     */
    public int updateHwProductCaseInfo(HwProductCaseInfo hwProductCaseInfo);

    /**
     * 删除案例内容
     * 
     * @param caseInfoId 案例内容主键
     * @return 结果
     */
    public int deleteHwProductCaseInfoByCaseInfoId(Long caseInfoId);

    /**
     * 批量删除案例内容
     * 
     * @param caseInfoIds 需要删除的数据主键集合
     * @return 结果
     */
    public int deleteHwProductCaseInfoByCaseInfoIds(Long[] caseInfoIds);

    /**
     * 查询案例内容列表,Join portalConfigType
     *
     * @param hwProductCaseInfo 案例内容
     * @return 案例内容集合
     */
    public List<HwProductCaseInfo> selectHwProductCaseInfoJoinList(HwProductCaseInfo hwProductCaseInfo);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/mapper/HwProductInfoDetailMapper.java

package com.ruoyi.portal.mapper;

import com.ruoyi.portal.domain.HwProductInfoDetail;

import java.util.List;

/**
 * 产品信息明细配置Mapper接口
 * 
 * @author xins
 * @date 2024-12-11
 */
public interface HwProductInfoDetailMapper 
{
    /**
     * 查询产品信息明细配置
     * 
     * @param productInfoDetailId 产品信息明细配置主键
     * @return 产品信息明细配置
     */
    public HwProductInfoDetail selectHwProductInfoDetailByProductInfoDetailId(Long productInfoDetailId);

    /**
     * 查询产品信息明细配置列表
     * 
     * @param hwProductInfoDetail 产品信息明细配置
     * @return 产品信息明细配置集合
     */
    public List<HwProductInfoDetail> selectHwProductInfoDetailList(HwProductInfoDetail hwProductInfoDetail);

    /**
     * 新增产品信息明细配置
     * 
     * @param hwProductInfoDetail 产品信息明细配置
     * @return 结果
     */
    public int insertHwProductInfoDetail(HwProductInfoDetail hwProductInfoDetail);

    /**
     * 修改产品信息明细配置
     * 
     * @param hwProductInfoDetail 产品信息明细配置
     * @return 结果
     */
    public int updateHwProductInfoDetail(HwProductInfoDetail hwProductInfoDetail);

    /**
     * 删除产品信息明细配置
     * 
     * @param productInfoDetailId 产品信息明细配置主键
     * @return 结果
     */
    public int deleteHwProductInfoDetailByProductInfoDetailId(Long productInfoDetailId);

    /**
     * 批量删除产品信息明细配置
     * 
     * @param productInfoDetailIds 需要删除的数据主键集合
     * @return 结果
     */
    public int deleteHwProductInfoDetailByProductInfoDetailIds(Long[] productInfoDetailIds);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/mapper/HwProductInfoMapper.java

package com.ruoyi.portal.mapper;

import com.ruoyi.portal.domain.HwProductInfo;

import java.util.List;

/**
 * 产品信息配置Mapper接口
 * 
 * @author xins
 * @date 2024-12-01
 */
public interface HwProductInfoMapper 
{
    /**
     * 查询产品信息配置
     * 
     * @param productInfoId 产品信息配置主键
     * @return 产品信息配置
     */
    public HwProductInfo selectHwProductInfoByProductInfoId(Long productInfoId);

    /**
     * 查询产品信息配置列表
     * 
     * @param hwProductInfo 产品信息配置
     * @return 产品信息配置集合
     */
    public List<HwProductInfo> selectHwProductInfoList(HwProductInfo hwProductInfo);

    /**
     * 新增产品信息配置
     * 
     * @param hwProductInfo 产品信息配置
     * @return 结果
     */
    public int insertHwProductInfo(HwProductInfo hwProductInfo);

    /**
     * 修改产品信息配置
     * 
     * @param hwProductInfo 产品信息配置
     * @return 结果
     */
    public int updateHwProductInfo(HwProductInfo hwProductInfo);

    /**
     * 删除产品信息配置
     * 
     * @param productInfoId 产品信息配置主键
     * @return 结果
     */
    public int deleteHwProductInfoByProductInfoId(Long productInfoId);

    /**
     * 批量删除产品信息配置
     * 
     * @param productInfoIds 需要删除的数据主键集合
     * @return 结果
     */
    public int deleteHwProductInfoByProductInfoIds(Long[] productInfoIds);

    /**
     * 查询产品信息配置列表,join product info detail
     *
     * @param hwProductInfo 产品信息配置
     * @return 产品信息配置集合
     */
    public List<HwProductInfo> selectHwProductInfoJoinDetailList(HwProductInfo hwProductInfo);

    /**
     * 查询产品信息配置列表,join portalConfigType门户网站配置类型
     *
     * @param hwProductInfo 产品信息配置
     * @return 产品信息配置集合
     */
    public List<HwProductInfo> selectHwProductInfoJoinList(HwProductInfo hwProductInfo);

}

ruoyi-portal/src/main/java/com/ruoyi/portal/mapper/HwSearchMapper.java

package com.ruoyi.portal.mapper;

import com.ruoyi.portal.domain.dto.SearchRawRecord;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * 门户搜索 Mapper
 *
 * @author ruoyi
 */
public interface HwSearchMapper
{
    /**
     * 关键词搜索原始数据
     *
     * @param keyword 关键词
     * @return 命中记录
     */
    List<SearchRawRecord> searchByKeyword(@Param("keyword") String keyword);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/mapper/HwWebDocumentMapper.java

package com.ruoyi.portal.mapper;

import java.util.List;
import com.ruoyi.portal.domain.HwWebDocument;

/**
 * Hw资料文件Mapper接口
 * 
 * @author zch
 * @date 2025-09-22
 */
public interface HwWebDocumentMapper 
{
    /**
     * 查询Hw资料文件
     * 
     * @param documentId Hw资料文件主键
     * @return Hw资料文件
     */
    public HwWebDocument selectHwWebDocumentByDocumentId(String documentId);

    /**
     * 查询Hw资料文件列表
     * 
     * @param hwWebDocument Hw资料文件
     * @return Hw资料文件集合
     */
    public List<HwWebDocument> selectHwWebDocumentList(HwWebDocument hwWebDocument);

    /**
     * 新增Hw资料文件
     * 
     * @param hwWebDocument Hw资料文件
     * @return 结果
     */
    public int insertHwWebDocument(HwWebDocument hwWebDocument);

    /**
     * 修改Hw资料文件
     * 
     * @param hwWebDocument Hw资料文件
     * @return 结果
     */
    public int updateHwWebDocument(HwWebDocument hwWebDocument);

    /**
     * 删除Hw资料文件
     * 
     * @param documentId Hw资料文件主键
     * @return 结果
     */
    public int deleteHwWebDocumentByDocumentId(String documentId);

    /**
     * 批量删除Hw资料文件
     * 
     * @param documentIds 需要删除的数据主键集合
     * @return 结果
     */
    public int deleteHwWebDocumentByDocumentIds(String[] documentIds);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/mapper/HwWebMapper.java

package com.ruoyi.portal.mapper;

import java.util.List;
import com.ruoyi.portal.domain.HwWeb;

/**
 * haiwei官网jsonMapper接口
 * 
 * @author ruoyi
 * @date 2025-08-18
 */
public interface HwWebMapper 
{
    /**
     * 查询haiwei官网json
     * 
     * @param webId haiwei官网json主键
     * @return haiwei官网json
     */
    public HwWeb selectHwWebByWebcode(Long webCode);

    /**
     * 查询haiwei官网json列表
     * 
     * @param hwWeb haiwei官网json
     * @return haiwei官网json集合
     */
    public List<HwWeb> selectHwWebList(HwWeb hwWeb);

    /**
     * 新增haiwei官网json
     * 
     * @param hwWeb haiwei官网json
     * @return 结果
     */
    public int insertHwWeb(HwWeb hwWeb);

    /**
     * 修改haiwei官网json
     * 
     * @param hwWeb haiwei官网json
     * @return 结果
     */
    public int updateHwWeb(HwWeb hwWeb);

    /**
     * 删除haiwei官网json
     * 
     * @param webId haiwei官网json主键
     * @return 结果
     */
    public int deleteHwWebByWebId(Long webId);

    /**
     * 批量删除haiwei官网json
     * 
     * @param webIds 需要删除的数据主键集合
     * @return 结果
     */
    public int deleteHwWebByWebIds(Long[] webIds);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/mapper/HwWebMapper1.java

package com.ruoyi.portal.mapper;

import com.ruoyi.portal.domain.HwWeb1;

import java.util.List;

/**
 * haiwei官网jsonMapper接口
 * 
 * @author ruoyi
 * @date 2025-08-18
 */
public interface HwWebMapper1
{
    /**
     * 查询haiwei官网json
     * 
     * @param webId haiwei官网json主键
     * @return haiwei官网json
     */
    public HwWeb1 selectHwWebByWebcode(Long webCode);

    /**
     * 查询haiwei官网json列表
     *
     * @param HwWeb1 haiwei官网json
     * @return haiwei官网json集合
     */
    public HwWeb1 selectHwWebOne(HwWeb1 hwWeb1);

    /**
     * 查询haiwei官网json列表
     * 
     * @param HwWeb1 haiwei官网json
     * @return haiwei官网json集合
     */
    public List<HwWeb1> selectHwWebList(HwWeb1 hwWeb1);

    /**
     * 新增haiwei官网json
     * 
     * @param HwWeb1 haiwei官网json
     * @return 结果
     */
    public int insertHwWeb(HwWeb1 hwWeb1);

    /**
     * 修改haiwei官网json
     * 
     * @param HwWeb1 haiwei官网json
     * @return 结果
     */
    public int updateHwWeb(HwWeb1 hwWeb1);

    /**
     * 删除haiwei官网json
     * 
     * @param webId haiwei官网json主键
     * @return 结果
     */
    public int deleteHwWebByWebId(Long webId);

    /**
     * 批量删除haiwei官网json
     * 
     * @param webIds 需要删除的数据主键集合
     * @return 结果
     */
    public int deleteHwWebByWebIds(Long[] webIds);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/mapper/HwWebMenuMapper.java

package com.ruoyi.portal.mapper;

import java.util.List;
import com.ruoyi.portal.domain.HwWebMenu;

/**
 * haiwei官网菜单Mapper接口
 * 
 * @author zch
 * @date 2025-08-18
 */
public interface HwWebMenuMapper 
{
    /**
     * 查询haiwei官网菜单
     * 
     * @param webMenuId haiwei官网菜单主键
     * @return haiwei官网菜单
     */
    public HwWebMenu selectHwWebMenuByWebMenuId(Long webMenuId);

    /**
     * 查询haiwei官网菜单列表
     * 
     * @param hwWebMenu haiwei官网菜单
     * @return haiwei官网菜单集合
     */
    public List<HwWebMenu> selectHwWebMenuList(HwWebMenu hwWebMenu);

    /**
     * 新增haiwei官网菜单
     * 
     * @param hwWebMenu haiwei官网菜单
     * @return 结果
     */
    public int insertHwWebMenu(HwWebMenu hwWebMenu);

    /**
     * 修改haiwei官网菜单
     * 
     * @param hwWebMenu haiwei官网菜单
     * @return 结果
     */
    public int updateHwWebMenu(HwWebMenu hwWebMenu);

    /**
     * 删除haiwei官网菜单
     * 
     * @param webMenuId haiwei官网菜单主键
     * @return 结果
     */
    public int deleteHwWebMenuByWebMenuId(Long webMenuId);

    /**
     * 批量删除haiwei官网菜单
     * 
     * @param webMenuIds 需要删除的数据主键集合
     * @return 结果
     */
    public int deleteHwWebMenuByWebMenuIds(Long[] webMenuIds);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/mapper/HwWebMenuMapper1.java

package com.ruoyi.portal.mapper;

import com.ruoyi.portal.domain.HwWebMenu;
import com.ruoyi.portal.domain.HwWebMenu1;
import com.ruoyi.portal.domain.HwWebMenu1;

import java.util.List;

/**
 * haiwei官网菜单Mapper接口
 * 
 * @author zch
 * @date 2025-08-18
 */
public interface HwWebMenuMapper1
{
    /**
     * 查询haiwei官网菜单
     * 
     * @param webMenuId haiwei官网菜单主键
     * @return haiwei官网菜单
     */
    public HwWebMenu1 selectHwWebMenuByWebMenuId(Long webMenuId);

    /**
     * 查询haiwei官网菜单列表
     * 
     * @param HwWebMenu1 haiwei官网菜单
     * @return haiwei官网菜单集合
     */
    public List<HwWebMenu1> selectHwWebMenuList(HwWebMenu1 HwWebMenu1);

    /**
     * 新增haiwei官网菜单
     * 
     * @param HwWebMenu1 haiwei官网菜单
     * @return 结果
     */
    public int insertHwWebMenu(HwWebMenu1 HwWebMenu1);

    /**
     * 修改haiwei官网菜单
     * 
     * @param HwWebMenu1 haiwei官网菜单
     * @return 结果
     */
    public int updateHwWebMenu(HwWebMenu1 HwWebMenu1);

    /**
     * 删除haiwei官网菜单
     * 
     * @param webMenuId haiwei官网菜单主键
     * @return 结果
     */
    public int deleteHwWebMenuByWebMenuId(Long webMenuId);

    /**
     * 批量删除haiwei官网菜单
     * 
     * @param webMenuIds 需要删除的数据主键集合
     * @return 结果
     */
    public int deleteHwWebMenuByWebMenuIds(Long[] webMenuIds);


    /**
     * 获取菜单树列表
     */
    public List<HwWebMenu1> selectMenuTree(HwWebMenu1 hwWebMenu);

}

ruoyi-portal/src/main/java/com/ruoyi/portal/search/convert/PortalSearchDocConverter.java

package com.ruoyi.portal.search.convert;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.portal.domain.HwPortalConfigType;
import com.ruoyi.portal.domain.HwWeb;
import com.ruoyi.portal.domain.HwWeb1;
import com.ruoyi.portal.domain.HwWebDocument;
import com.ruoyi.portal.domain.HwWebMenu;
import com.ruoyi.portal.search.es.entity.PortalSearchDoc;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 搜索文档转换器
 *
 * @author ruoyi
 */
@Component
public class PortalSearchDocConverter
{
    public static final String SOURCE_MENU = "menu";
    public static final String SOURCE_WEB = "web";
    public static final String SOURCE_WEB1 = "web1";
    public static final String SOURCE_DOCUMENT = "document";
    public static final String SOURCE_CONFIG_TYPE = "configType";

    private static final Set<String> SKIP_JSON_KEYS = new HashSet<>(Arrays.asList(
            "icon", "url", "banner", "banner1", "img", "imglist", "type", "uuid", "filename",
            "documentaddress", "secretkey", "route", "routequery", "webcode", "deviceid", "typeid",
            "configtypeid", "id"
    ));

    private final ObjectMapper objectMapper = new ObjectMapper();

    public PortalSearchDoc fromWebMenu(HwWebMenu menu)
    {
        PortalSearchDoc doc = initBase();
        String id = "menu:" + menu.getWebMenuId();
        doc.setId(id);
        doc.setDocId(id);
        doc.setSourceType(SOURCE_MENU);
        doc.setTitle(menu.getWebMenuName());
        doc.setContent(joinText(menu.getWebMenuName(), menu.getAncestors()));
        doc.setMenuId(String.valueOf(menu.getWebMenuId()));
        doc.setRoute("/test");
        doc.setRouteQueryJson(toJson(Map.of("id", menu.getWebMenuId())));
        doc.setUpdatedAt(new Date());
        return doc;
    }

    public PortalSearchDoc fromWeb(HwWeb web)
    {
        PortalSearchDoc doc = initBase();
        String webCode = toString(web.getWebCode());
        String id = "web:" + webCode;
        doc.setId(id);
        doc.setDocId(id);
        doc.setSourceType(SOURCE_WEB);
        doc.setTitle("页面#" + webCode);
        doc.setContent(extractSearchableText(web.getWebJsonString()));
        doc.setWebCode(webCode);
        if ("-1".equals(webCode))
        {
            doc.setRoute("/index");
            doc.setRouteQueryJson("{}");
        }
        else if ("7".equals(webCode))
        {
            doc.setRoute("/productCenter");
            doc.setRouteQueryJson("{}");
        }
        else
        {
            doc.setRoute("/test");
            doc.setRouteQueryJson(toJson(Map.of("id", webCode)));
        }
        doc.setUpdatedAt(new Date());
        return doc;
    }

    public PortalSearchDoc fromWeb1(HwWeb1 web1)
    {
        PortalSearchDoc doc = initBase();
        String webCode = toString(web1.getWebCode());
        String typeId = toString(web1.getTypeId());
        String deviceId = toString(web1.getDeviceId());
        String id = String.format("web1:%s:%s:%s", webCode, typeId, deviceId);
        doc.setId(id);
        doc.setDocId(id);
        doc.setSourceType(SOURCE_WEB1);
        doc.setTitle("详情#" + webCode + "-" + typeId + "-" + deviceId);
        doc.setContent(extractSearchableText(web1.getWebJsonString()));
        doc.setWebCode(webCode);
        doc.setTypeId(typeId);
        doc.setDeviceId(deviceId);
        doc.setRoute("/productCenter/detail");
        doc.setRouteQueryJson(toJson(Map.of("webCode", webCode, "typeId", typeId, "deviceId", deviceId)));
        doc.setUpdatedAt(new Date());
        return doc;
    }

    public PortalSearchDoc fromDocument(HwWebDocument document)
    {
        PortalSearchDoc doc = initBase();
        String id = "doc:" + document.getDocumentId();
        doc.setId(id);
        doc.setDocId(id);
        doc.setSourceType(SOURCE_DOCUMENT);
        String title = StringUtils.isNotBlank(document.getJson()) ? document.getJson() : document.getDocumentId();
        doc.setTitle(title);
        doc.setContent(StringUtils.defaultString(document.getJson()));
        doc.setDocumentId(document.getDocumentId());
        doc.setWebCode(document.getWebCode());
        doc.setTypeId(document.getType());
        doc.setRoute("/serviceSupport");
        doc.setRouteQueryJson(toJson(Map.of("documentId", document.getDocumentId())));
        doc.setUpdatedAt(new Date());
        return doc;
    }

    public PortalSearchDoc fromConfigType(HwPortalConfigType configType)
    {
        PortalSearchDoc doc = initBase();
        String id = "configType:" + configType.getConfigTypeId();
        doc.setId(id);
        doc.setDocId(id);
        doc.setSourceType(SOURCE_CONFIG_TYPE);
        doc.setTitle(configType.getConfigTypeName());
        doc.setContent(joinText(configType.getConfigTypeName(), configType.getHomeConfigTypeName(), configType.getConfigTypeDesc()));
        doc.setTypeId(toString(configType.getConfigTypeId()));
        doc.setRoute("/productCenter");
        doc.setRouteQueryJson(toJson(Map.of("configTypeId", configType.getConfigTypeId())));
        doc.setUpdatedAt(new Date());
        return doc;
    }

    public String extractSearchableText(String text)
    {
        if (StringUtils.isBlank(text))
        {
            return StringUtils.EMPTY;
        }
        String stripped = stripHtml(text);
        try
        {
            JsonNode root = objectMapper.readTree(text);
            StringBuilder builder = new StringBuilder();
            collectNodeText(root, null, builder);
            String extracted = normalizeWhitespace(builder.toString());
            return StringUtils.isBlank(extracted) ? stripped : extracted;
        }
        catch (Exception ignored)
        {
            return stripped;
        }
    }

    private void collectNodeText(JsonNode node, String fieldName, StringBuilder out)
    {
        if (node == null || node.isNull())
        {
            return;
        }
        if (node.isObject())
        {
            node.fields().forEachRemaining(entry ->
            {
                if (!shouldSkip(entry.getKey()))
                {
                    collectNodeText(entry.getValue(), entry.getKey(), out);
                }
            });
            return;
        }
        if (node.isArray())
        {
            for (JsonNode child : node)
            {
                collectNodeText(child, fieldName, out);
            }
            return;
        }
        if (node.isTextual())
        {
            if (shouldSkip(fieldName))
            {
                return;
            }
            String value = normalizeWhitespace(stripHtml(node.asText()));
            if (StringUtils.isBlank(value))
            {
                return;
            }
            if (value.startsWith("http://") || value.startsWith("https://"))
            {
                return;
            }
            out.append(value).append(' ');
        }
    }

    private boolean shouldSkip(String fieldName)
    {
        if (StringUtils.isBlank(fieldName))
        {
            return false;
        }
        String normalized = fieldName.toLowerCase();
        return SKIP_JSON_KEYS.contains(normalized) || normalized.endsWith("url") || normalized.endsWith("icon");
    }

    private PortalSearchDoc initBase()
    {
        PortalSearchDoc doc = new PortalSearchDoc();
        doc.setIsDelete("0");
        return doc;
    }

    private String joinText(String... parts)
    {
        return Arrays.stream(parts)
                .filter(StringUtils::isNotBlank)
                .map(this::normalizeWhitespace)
                .collect(Collectors.joining(" "));
    }

    private String stripHtml(String text)
    {
        if (StringUtils.isBlank(text))
        {
            return StringUtils.EMPTY;
        }
        String noTags = text.replaceAll("<[^>]+>", " ");
        return normalizeWhitespace(noTags);
    }

    private String normalizeWhitespace(String value)
    {
        if (value == null)
        {
            return StringUtils.EMPTY;
        }
        return value.replaceAll("\\s+", " ").trim();
    }

    private String toString(Object value)
    {
        return value == null ? null : String.valueOf(value);
    }

    private String toJson(Map<String, Object> routeQuery)
    {
        try
        {
            return objectMapper.writeValueAsString(routeQuery);
        }
        catch (Exception e)
        {
            return "{}";
        }
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/search/es/entity/PortalSearchDoc.java

package com.ruoyi.portal.search.es.entity;

import org.dromara.easyes.annotation.HighLight;
import org.dromara.easyes.annotation.IndexField;
import org.dromara.easyes.annotation.IndexId;
import org.dromara.easyes.annotation.IndexName;
import org.dromara.easyes.annotation.rely.Analyzer;
import org.dromara.easyes.annotation.rely.FieldType;
import org.dromara.easyes.annotation.rely.IdType;

import java.util.Date;

/**
 * 门户搜索文档
 *
 * @author ruoyi
 */
@IndexName("hw_portal_content")
public class PortalSearchDoc
{
    @IndexId(type = IdType.NONE)
    private String id;

    @IndexField(fieldType = FieldType.KEYWORD)
    private String docId;

    @IndexField(fieldType = FieldType.KEYWORD)
    private String sourceType;

    @HighLight(preTag = "<em class='search-hit'>", postTag = "</em>")
    @IndexField(fieldType = FieldType.TEXT, analyzer = Analyzer.IK_MAX_WORD, searchAnalyzer = Analyzer.IK_SMART)
    private String title;

    @HighLight(preTag = "<em class='search-hit'>", postTag = "</em>")
    @IndexField(fieldType = FieldType.TEXT, analyzer = Analyzer.IK_MAX_WORD, searchAnalyzer = Analyzer.IK_SMART)
    private String content;

    @IndexField(fieldType = FieldType.KEYWORD)
    private String webCode;

    @IndexField(fieldType = FieldType.KEYWORD)
    private String typeId;

    @IndexField(fieldType = FieldType.KEYWORD)
    private String deviceId;

    @IndexField(fieldType = FieldType.KEYWORD)
    private String menuId;

    @IndexField(fieldType = FieldType.KEYWORD)
    private String documentId;

    @IndexField(fieldType = FieldType.KEYWORD)
    private String route;

    private String routeQueryJson;

    @IndexField(fieldType = FieldType.KEYWORD)
    private String isDelete;

    private Date updatedAt;

    public String getId()
    {
        return id;
    }

    public void setId(String id)
    {
        this.id = id;
    }

    public String getDocId()
    {
        return docId;
    }

    public void setDocId(String docId)
    {
        this.docId = docId;
    }

    public String getSourceType()
    {
        return sourceType;
    }

    public void setSourceType(String sourceType)
    {
        this.sourceType = sourceType;
    }

    public String getTitle()
    {
        return title;
    }

    public void setTitle(String title)
    {
        this.title = title;
    }

    public String getContent()
    {
        return content;
    }

    public void setContent(String content)
    {
        this.content = content;
    }

    public String getWebCode()
    {
        return webCode;
    }

    public void setWebCode(String webCode)
    {
        this.webCode = webCode;
    }

    public String getTypeId()
    {
        return typeId;
    }

    public void setTypeId(String typeId)
    {
        this.typeId = typeId;
    }

    public String getDeviceId()
    {
        return deviceId;
    }

    public void setDeviceId(String deviceId)
    {
        this.deviceId = deviceId;
    }

    public String getMenuId()
    {
        return menuId;
    }

    public void setMenuId(String menuId)
    {
        this.menuId = menuId;
    }

    public String getDocumentId()
    {
        return documentId;
    }

    public void setDocumentId(String documentId)
    {
        this.documentId = documentId;
    }

    public String getRoute()
    {
        return route;
    }

    public void setRoute(String route)
    {
        this.route = route;
    }

    public String getRouteQueryJson()
    {
        return routeQueryJson;
    }

    public void setRouteQueryJson(String routeQueryJson)
    {
        this.routeQueryJson = routeQueryJson;
    }

    public String getIsDelete()
    {
        return isDelete;
    }

    public void setIsDelete(String isDelete)
    {
        this.isDelete = isDelete;
    }

    public Date getUpdatedAt()
    {
        return updatedAt;
    }

    public void setUpdatedAt(Date updatedAt)
    {
        this.updatedAt = updatedAt;
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/search/es/mapper/PortalSearchMapper.java

package com.ruoyi.portal.search.es.mapper;

import com.ruoyi.portal.search.es.entity.PortalSearchDoc;
import org.dromara.easyes.core.kernel.BaseEsMapper;

/**
 * 门户搜索 ES Mapper
 *
 * @author ruoyi
 */
public interface PortalSearchMapper extends BaseEsMapper<PortalSearchDoc>
{
}

ruoyi-portal/src/main/java/com/ruoyi/portal/search/service/impl/PortalSearchEsServiceImpl.java

package com.ruoyi.portal.search.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.portal.domain.dto.SearchPageDTO;
import com.ruoyi.portal.domain.dto.SearchResultDTO;
import com.ruoyi.portal.search.convert.PortalSearchDocConverter;
import com.ruoyi.portal.search.es.entity.PortalSearchDoc;
import com.ruoyi.portal.search.es.mapper.PortalSearchMapper;
import com.ruoyi.portal.search.service.PortalSearchEsService;
import org.dromara.easyes.core.biz.EsPageInfo;
import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * ES 搜索服务实现
 *
 * @author ruoyi
 */
@Service
public class PortalSearchEsServiceImpl implements PortalSearchEsService
{
    private static final Logger log = LoggerFactory.getLogger(PortalSearchEsServiceImpl.class);

    private static final Pattern ESCAPE_PATTERN = Pattern.compile("([\\\\.*+\\[\\](){}^$?|])");

    private final PortalSearchMapper portalSearchMapper;

    private final ObjectMapper objectMapper = new ObjectMapper();

    public PortalSearchEsServiceImpl(PortalSearchMapper portalSearchMapper)
    {
        this.portalSearchMapper = portalSearchMapper;
    }

    @Override
    public SearchPageDTO search(String keyword, Integer pageNum, Integer pageSize, boolean editMode)
    {
        LambdaEsQueryWrapper<PortalSearchDoc> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.and(q -> q.match(PortalSearchDoc::getTitle, keyword, 5.0f).or().match(PortalSearchDoc::getContent, keyword, 2.0f));
        wrapper.eq(PortalSearchDoc::getIsDelete, "0");

        EsPageInfo<PortalSearchDoc> pageInfo = portalSearchMapper.pageQuery(wrapper, pageNum, pageSize);

        List<SearchResultDTO> rows = pageInfo.getList().stream().map(doc -> toResult(doc, keyword, editMode)).collect(Collectors.toList());
        SearchPageDTO page = new SearchPageDTO();
        page.setRows(rows);
        page.setTotal(pageInfo.getTotal());
        return page;
    }

    private SearchResultDTO toResult(PortalSearchDoc doc, String keyword, boolean editMode)
    {
        SearchResultDTO result = new SearchResultDTO();
        result.setSourceType(doc.getSourceType());
        result.setTitle(doc.getTitle());
        result.setSnippet(buildSnippet(doc.getTitle(), doc.getContent(), keyword));
        result.setScore(0);
        result.setRoute(doc.getRoute());
        result.setRouteQuery(parseRouteQuery(doc.getRouteQueryJson()));
        if (editMode)
        {
            result.setEditRoute(buildEditRoute(doc.getSourceType(), doc.getWebCode(), doc.getTypeId(), doc.getDeviceId(), doc.getMenuId(), doc.getDocumentId()));
        }
        return result;
    }

    private Map<String, Object> parseRouteQuery(String json)
    {
        if (StringUtils.isBlank(json))
        {
            return new HashMap<>();
        }
        try
        {
            return objectMapper.readValue(json, new TypeReference<Map<String, Object>>()
            {
            });
        }
        catch (Exception e)
        {
            log.warn("parse routeQueryJson failed: {}", json);
            return new HashMap<>();
        }
    }

    private String buildSnippet(String title, String content, String keyword)
    {
        if (StringUtils.isNotBlank(title) && StringUtils.containsIgnoreCase(title, keyword))
        {
            return highlight(title, keyword);
        }
        String normalized = StringUtils.defaultString(content);
        if (StringUtils.isBlank(normalized))
        {
            return StringUtils.EMPTY;
        }
        int idx = StringUtils.indexOfIgnoreCase(normalized, keyword);
        if (idx < 0)
        {
            return StringUtils.substring(normalized, 0, Math.min(120, normalized.length()));
        }
        int start = Math.max(0, idx - 60);
        int end = Math.min(normalized.length(), idx + keyword.length() + 60);
        String snippet = normalized.substring(start, end);
        if (start > 0)
        {
            snippet = "..." + snippet;
        }
        if (end < normalized.length())
        {
            snippet = snippet + "...";
        }
        return highlight(snippet, keyword);
    }

    private String highlight(String text, String keyword)
    {
        if (StringUtils.isBlank(text) || StringUtils.isBlank(keyword))
        {
            return StringUtils.defaultString(text);
        }
        String escaped = ESCAPE_PATTERN.matcher(keyword).replaceAll("\\\\$1");
        Matcher matcher = Pattern.compile("(?i)" + escaped).matcher(text);
        if (!matcher.find())
        {
            return text;
        }
        return matcher.replaceAll("<em class=\"search-hit\">$0</em>");
    }

    private String buildEditRoute(String sourceType, String webCode, String typeId, String deviceId, String menuId, String documentId)
    {
        if (PortalSearchDocConverter.SOURCE_MENU.equals(sourceType))
        {
            return "/editor?type=1&id=" + menuId;
        }
        if (PortalSearchDocConverter.SOURCE_WEB.equals(sourceType))
        {
            if ("7".equals(webCode))
            {
                return "/productCenter/edit";
            }
            if ("-1".equals(webCode))
            {
                return "/editor?type=3&id=-1";
            }
            return "/editor?type=1&id=" + webCode;
        }
        if (PortalSearchDocConverter.SOURCE_WEB1.equals(sourceType))
        {
            return "/editor?type=2&id=" + webCode + "," + typeId + "," + deviceId;
        }
        if (PortalSearchDocConverter.SOURCE_DOCUMENT.equals(sourceType))
        {
            if (StringUtils.isNotBlank(webCode) && StringUtils.isNotBlank(typeId) && StringUtils.isNotBlank(deviceId))
            {
                return "/editor?type=2&id=" + webCode + "," + typeId + "," + deviceId + "&documentId=" + documentId;
            }
            return "/editor?type=2&documentId=" + documentId;
        }
        if (PortalSearchDocConverter.SOURCE_CONFIG_TYPE.equals(sourceType))
        {
            return "/productCenter/edit";
        }
        return "/editor";
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/search/service/PortalSearchEsService.java

package com.ruoyi.portal.search.service;

import com.ruoyi.portal.domain.dto.SearchPageDTO;

/**
 * ES 搜索服务
 *
 * @author ruoyi
 */
public interface PortalSearchEsService
{
    /**
     * ES 查询
     *
     * @param keyword 关键词
     * @param pageNum 页码
     * @param pageSize 每页条数
     * @param editMode 是否编辑端模式
     * @return 搜索结果
     */
    SearchPageDTO search(String keyword, Integer pageNum, Integer pageSize, boolean editMode);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/IHwAboutUsInfoDetailService.java

package com.ruoyi.portal.service;

import com.ruoyi.portal.domain.HwAboutUsInfoDetail;

import java.util.List;

/**
 * 关于我们信息明细Service接口
 * 
 * @author ruoyi
 * @date 2024-12-01
 */
public interface IHwAboutUsInfoDetailService 
{
    /**
     * 查询关于我们信息明细
     * 
     * @param usInfoDetailId 关于我们信息明细主键
     * @return 关于我们信息明细
     */
    public HwAboutUsInfoDetail selectHwAboutUsInfoDetailByUsInfoDetailId(Long usInfoDetailId);

    /**
     * 查询关于我们信息明细列表
     * 
     * @param hwAboutUsInfoDetail 关于我们信息明细
     * @return 关于我们信息明细集合
     */
    public List<HwAboutUsInfoDetail> selectHwAboutUsInfoDetailList(HwAboutUsInfoDetail hwAboutUsInfoDetail);

    /**
     * 新增关于我们信息明细
     * 
     * @param hwAboutUsInfoDetail 关于我们信息明细
     * @return 结果
     */
    public int insertHwAboutUsInfoDetail(HwAboutUsInfoDetail hwAboutUsInfoDetail);

    /**
     * 修改关于我们信息明细
     * 
     * @param hwAboutUsInfoDetail 关于我们信息明细
     * @return 结果
     */
    public int updateHwAboutUsInfoDetail(HwAboutUsInfoDetail hwAboutUsInfoDetail);

    /**
     * 批量删除关于我们信息明细
     * 
     * @param usInfoDetailIds 需要删除的关于我们信息明细主键集合
     * @return 结果
     */
    public int deleteHwAboutUsInfoDetailByUsInfoDetailIds(Long[] usInfoDetailIds);

    /**
     * 删除关于我们信息明细信息
     * 
     * @param usInfoDetailId 关于我们信息明细主键
     * @return 结果
     */
    public int deleteHwAboutUsInfoDetailByUsInfoDetailId(Long usInfoDetailId);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/IHwAboutUsInfoService.java

package com.ruoyi.portal.service;

import com.ruoyi.portal.domain.HwAboutUsInfo;

import java.util.List;

/**
 * 关于我们信息Service接口
 * 
 * @author xins
 * @date 2024-12-01
 */
public interface IHwAboutUsInfoService 
{
    /**
     * 查询关于我们信息
     * 
     * @param aboutUsInfoId 关于我们信息主键
     * @return 关于我们信息
     */
    public HwAboutUsInfo selectHwAboutUsInfoByAboutUsInfoId(Long aboutUsInfoId);

    /**
     * 查询关于我们信息列表
     * 
     * @param hwAboutUsInfo 关于我们信息
     * @return 关于我们信息集合
     */
    public List<HwAboutUsInfo> selectHwAboutUsInfoList(HwAboutUsInfo hwAboutUsInfo);

    /**
     * 新增关于我们信息
     * 
     * @param hwAboutUsInfo 关于我们信息
     * @return 结果
     */
    public int insertHwAboutUsInfo(HwAboutUsInfo hwAboutUsInfo);

    /**
     * 修改关于我们信息
     * 
     * @param hwAboutUsInfo 关于我们信息
     * @return 结果
     */
    public int updateHwAboutUsInfo(HwAboutUsInfo hwAboutUsInfo);

    /**
     * 批量删除关于我们信息
     * 
     * @param aboutUsInfoIds 需要删除的关于我们信息主键集合
     * @return 结果
     */
    public int deleteHwAboutUsInfoByAboutUsInfoIds(Long[] aboutUsInfoIds);

    /**
     * 删除关于我们信息信息
     * 
     * @param aboutUsInfoId 关于我们信息主键
     * @return 结果
     */
    public int deleteHwAboutUsInfoByAboutUsInfoId(Long aboutUsInfoId);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/IHwAnalyticsService.java

package com.ruoyi.portal.service;

import com.ruoyi.portal.domain.dto.AnalyticsCollectRequest;
import com.ruoyi.portal.domain.dto.AnalyticsDashboardDTO;

import java.time.LocalDate;

/**
 * 官网访问监控服务
 *
 * @author ruoyi
 */
public interface IHwAnalyticsService
{
    /**
     * 采集匿名访问事件
     *
     * @param request 采集请求
     * @param requestIp 请求 IP
     * @param requestUserAgent 请求 UA
     */
    void collect(AnalyticsCollectRequest request, String requestIp, String requestUserAgent);

    /**
     * 查询日看板
     *
     * @param statDate 统计日期
     * @param rankLimit 排行数量
     * @return 看板数据
     */
    AnalyticsDashboardDTO getDashboard(LocalDate statDate, Integer rankLimit);

    /**
     * 刷新日汇总
     *
     * @param statDate 日期
     */
    void refreshDailyStat(LocalDate statDate);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/IHwContactUsInfoService.java

package com.ruoyi.portal.service;

import com.ruoyi.portal.domain.HwContactUsInfo;

import java.util.List;

/**
 * 联系我们信息Service接口
 * 
 * @author xins
 * @date 2024-12-01
 */
public interface IHwContactUsInfoService 
{
    /**
     * 查询联系我们信息
     * 
     * @param contactUsInfoId 联系我们信息主键
     * @return 联系我们信息
     */
    public HwContactUsInfo selectHwContactUsInfoByContactUsInfoId(Long contactUsInfoId);

    /**
     * 查询联系我们信息列表
     * 
     * @param hwContactUsInfo 联系我们信息
     * @return 联系我们信息集合
     */
    public List<HwContactUsInfo> selectHwContactUsInfoList(HwContactUsInfo hwContactUsInfo);

    /**
     * 新增联系我们信息
     * 
     * @param hwContactUsInfo 联系我们信息
     * @return 结果
     */
    public int insertHwContactUsInfo(HwContactUsInfo hwContactUsInfo);

    /**
     * 修改联系我们信息
     * 
     * @param hwContactUsInfo 联系我们信息
     * @return 结果
     */
    public int updateHwContactUsInfo(HwContactUsInfo hwContactUsInfo);

    /**
     * 批量删除联系我们信息
     * 
     * @param contactUsInfoIds 需要删除的联系我们信息主键集合
     * @return 结果
     */
    public int deleteHwContactUsInfoByContactUsInfoIds(Long[] contactUsInfoIds);

    /**
     * 删除联系我们信息信息
     * 
     * @param contactUsInfoId 联系我们信息主键
     * @return 结果
     */
    public int deleteHwContactUsInfoByContactUsInfoId(Long contactUsInfoId);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/IHwPortalConfigService.java

package com.ruoyi.portal.service;

import com.ruoyi.portal.domain.HwPortalConfig;

import java.util.List;

/**
 * 门户网站配置Service接口
 * 
 * @author xins
 * @date 2024-12-01
 */
public interface IHwPortalConfigService 
{
    /**
     * 查询门户网站配置
     * 
     * @param portalConfigId 门户网站配置主键
     * @return 门户网站配置
     */
    public HwPortalConfig selectHwPortalConfigByPortalConfigId(Long portalConfigId);

    /**
     * 查询门户网站配置列表
     * 
     * @param hwPortalConfig 门户网站配置
     * @return 门户网站配置集合
     */
    public List<HwPortalConfig> selectHwPortalConfigList(HwPortalConfig hwPortalConfig);

    /**
     * 新增门户网站配置
     * 
     * @param hwPortalConfig 门户网站配置
     * @return 结果
     */
    public int insertHwPortalConfig(HwPortalConfig hwPortalConfig);

    /**
     * 修改门户网站配置
     * 
     * @param hwPortalConfig 门户网站配置
     * @return 结果
     */
    public int updateHwPortalConfig(HwPortalConfig hwPortalConfig);

    /**
     * 批量删除门户网站配置
     * 
     * @param portalConfigIds 需要删除的门户网站配置主键集合
     * @return 结果
     */
    public int deleteHwPortalConfigByPortalConfigIds(Long[] portalConfigIds);

    /**
     * 删除门户网站配置信息
     * 
     * @param portalConfigId 门户网站配置主键
     * @return 结果
     */
    public int deleteHwPortalConfigByPortalConfigId(Long portalConfigId);

    /**
     * 查询门户网站配置列表,Join hw_portal_config_type
     *
     * @param hwPortalConfig 门户网站配置
     * @return 门户网站配置
     */
    public List<HwPortalConfig> selectHwPortalConfigJoinList(HwPortalConfig hwPortalConfig);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/IHwPortalConfigTypeService.java

package com.ruoyi.portal.service;

import com.ruoyi.portal.domain.HwPortalConfigType;
import com.ruoyi.portal.domain.vo.TreeSelect;

import java.util.List;

/**
 * 门户网站配置类型Service接口
 * 
 * @author xins
 * @date 2024-12-11
 */
public interface IHwPortalConfigTypeService 
{
    /**
     * 查询门户网站配置类型
     * 
     * @param configTypeId 门户网站配置类型主键
     * @return 门户网站配置类型
     */
    public HwPortalConfigType selectHwPortalConfigTypeByConfigTypeId(Long configTypeId);

    /**
     * 查询门户网站配置类型列表
     * 
     * @param hwPortalConfigType 门户网站配置类型
     * @return 门户网站配置类型集合
     */
    public List<HwPortalConfigType> selectHwPortalConfigTypeList(HwPortalConfigType hwPortalConfigType);


    /**
     * 查询门户网站配置类型列表
     *
     * @param hwPortalConfigType 门户网站配置类型
     * @return 门户网站配置类型集合
     */
    public List<HwPortalConfigType> selectConfigTypeList(HwPortalConfigType hwPortalConfigType);

    /**
     * 新增门户网站配置类型
     * 
     * @param hwPortalConfigType 门户网站配置类型
     * @return 结果
     */
    public int insertHwPortalConfigType(HwPortalConfigType hwPortalConfigType);

    /**
     * 修改门户网站配置类型
     * 
     * @param hwPortalConfigType 门户网站配置类型
     * @return 结果
     */
    public int updateHwPortalConfigType(HwPortalConfigType hwPortalConfigType);

    /**
     * 批量删除门户网站配置类型
     * 
     * @param configTypeIds 需要删除的门户网站配置类型主键集合
     * @return 结果
     */
    public int deleteHwPortalConfigTypeByConfigTypeIds(Long[] configTypeIds);

    /**
     * 删除门户网站配置类型信息
     * 
     * @param configTypeId 门户网站配置类型主键
     * @return 结果
     */
    public int deleteHwPortalConfigTypeByConfigTypeId(Long configTypeId);

    /**
     * 查询门户网站配置类型树结构信息
     *
     * @param portalConfigType 门户网站配置类型信息
     * @return 门户网站配置类型树信息集合
     */
    public List<TreeSelect> selectPortalConfigTypeTreeList(HwPortalConfigType portalConfigType);

    /**
     * 构建前端所需要下拉树结构
     *
     * @param portalConfigTypes 门户网站配置类型列表
     * @return 下拉树结构列表
     */
    public List<TreeSelect> buildPortalConfigTypeTreeSelect(List<HwPortalConfigType> portalConfigTypes);
    /**
     * 构建前端所需要树结构
     *
     * @param portalConfigTypes 门户网站配置类型列表
     * @return 树结构列表
     */
    public List<HwPortalConfigType> buildPortalConfigTypeTree(List<HwPortalConfigType> portalConfigTypes);

}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/IHwProductCaseInfoService.java

package com.ruoyi.portal.service;

import com.ruoyi.portal.domain.HwProductCaseInfo;

import java.util.List;

/**
 * 案例内容Service接口
 * 
 * @author xins
 * @date 2024-12-01
 */
public interface IHwProductCaseInfoService 
{
    /**
     * 查询案例内容
     * 
     * @param caseInfoId 案例内容主键
     * @return 案例内容
     */
    public HwProductCaseInfo selectHwProductCaseInfoByCaseInfoId(Long caseInfoId);

    /**
     * 查询案例内容列表
     * 
     * @param hwProductCaseInfo 案例内容
     * @return 案例内容集合
     */
    public List<HwProductCaseInfo> selectHwProductCaseInfoList(HwProductCaseInfo hwProductCaseInfo);

    /**
     * 新增案例内容
     * 
     * @param hwProductCaseInfo 案例内容
     * @return 结果
     */
    public int insertHwProductCaseInfo(HwProductCaseInfo hwProductCaseInfo);

    /**
     * 修改案例内容
     * 
     * @param hwProductCaseInfo 案例内容
     * @return 结果
     */
    public int updateHwProductCaseInfo(HwProductCaseInfo hwProductCaseInfo);

    /**
     * 批量删除案例内容
     * 
     * @param caseInfoIds 需要删除的案例内容主键集合
     * @return 结果
     */
    public int deleteHwProductCaseInfoByCaseInfoIds(Long[] caseInfoIds);

    /**
     * 删除案例内容信息
     * 
     * @param caseInfoId 案例内容主键
     * @return 结果
     */
    public int deleteHwProductCaseInfoByCaseInfoId(Long caseInfoId);

    /**
     * 根据configTypeId获取首页典型案例
     * @param hwProductCaseInfo
     * @return
     */
    public HwProductCaseInfo getTypicalHomeCaseInfo(HwProductCaseInfo hwProductCaseInfo);

    /**
     * 查询案例内容列表,join portalConfigType
     *
     * @param hwProductCaseInfo 案例内容
     * @return 案例内容
     */
    public List<HwProductCaseInfo> selectHwProductCaseInfoJoinList(HwProductCaseInfo hwProductCaseInfo);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/IHwProductInfoDetailService.java

package com.ruoyi.portal.service;

import com.ruoyi.portal.domain.HwProductInfoDetail;

import java.util.List;

/**
 * 产品信息明细配置Service接口
 * 
 * @author xins
 * @date 2024-12-11
 */
public interface IHwProductInfoDetailService 
{
    /**
     * 查询产品信息明细配置
     * 
     * @param productInfoDetailId 产品信息明细配置主键
     * @return 产品信息明细配置
     */
    public HwProductInfoDetail selectHwProductInfoDetailByProductInfoDetailId(Long productInfoDetailId);

    /**
     * 查询产品信息明细配置列表
     * 
     * @param hwProductInfoDetail 产品信息明细配置
     * @return 产品信息明细配置集合
     */
    public List<HwProductInfoDetail> selectHwProductInfoDetailList(HwProductInfoDetail hwProductInfoDetail);

    /**
     * 新增产品信息明细配置
     * 
     * @param hwProductInfoDetail 产品信息明细配置
     * @return 结果
     */
    public int insertHwProductInfoDetail(HwProductInfoDetail hwProductInfoDetail);

    /**
     * 修改产品信息明细配置
     * 
     * @param hwProductInfoDetail 产品信息明细配置
     * @return 结果
     */
    public int updateHwProductInfoDetail(HwProductInfoDetail hwProductInfoDetail);

    /**
     * 批量删除产品信息明细配置
     * 
     * @param productInfoDetailIds 需要删除的产品信息明细配置主键集合
     * @return 结果
     */
    public int deleteHwProductInfoDetailByProductInfoDetailIds(Long[] productInfoDetailIds);

    /**
     * 删除产品信息明细配置信息
     * 
     * @param productInfoDetailId 产品信息明细配置主键
     * @return 结果
     */
    public int deleteHwProductInfoDetailByProductInfoDetailId(Long productInfoDetailId);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/IHwProductInfoService.java

package com.ruoyi.portal.service;

import com.ruoyi.portal.domain.HwProductInfo;

import java.util.List;

/**
 * 产品信息配置Service接口
 * 
 * @author xins
 * @date 2024-12-01
 */
public interface IHwProductInfoService 
{
    /**
     * 查询产品信息配置
     * 
     * @param productInfoId 产品信息配置主键
     * @return 产品信息配置
     */
    public HwProductInfo selectHwProductInfoByProductInfoId(Long productInfoId);

    /**
     * 查询产品信息配置列表
     * 
     * @param hwProductInfo 产品信息配置
     * @return 产品信息配置集合
     */
    public List<HwProductInfo> selectHwProductInfoList(HwProductInfo hwProductInfo);

    /**
     * 新增产品信息配置
     * 
     * @param hwProductInfo 产品信息配置
     * @return 结果
     */
    public int insertHwProductInfo(HwProductInfo hwProductInfo);

    /**
     * 修改产品信息配置
     * 
     * @param hwProductInfo 产品信息配置
     * @return 结果
     */
    public int updateHwProductInfo(HwProductInfo hwProductInfo);

    /**
     * 批量删除产品信息配置
     * 
     * @param productInfoIds 需要删除的产品信息配置主键集合
     * @return 结果
     */
    public int deleteHwProductInfoByProductInfoIds(Long[] productInfoIds);

    /**
     * 删除产品信息配置信息
     * 
     * @param productInfoId 产品信息配置主键
     * @return 结果
     */
    public int deleteHwProductInfoByProductInfoId(Long productInfoId);

    /**
     * 获取产品中心产品信息(平台简介,hw_product_info获取配置模式2左标题+内容右图片读取中文标题和英文标题下面内容从hw_product_info_detail获取读取标题内容和图片)
     *
     * @param hwProductInfo 产品信息配置
     * @return 产品信息配置
     */
    public List<HwProductInfo> selectHwProductInfoJoinDetailList(HwProductInfo hwProductInfo);

    /**
     * 查询产品信息配置列表,join portalConfigType
     *
     * @param hwProductInfo 产品信息配置
     * @return 产品信息配置
     */
    public List<HwProductInfo> selectHwProductInfoJoinList(HwProductInfo hwProductInfo);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/IHwSearchRebuildService.java

package com.ruoyi.portal.service;

/**
 * 门户搜索索引重建服务
 *
 * @author ruoyi
 */
public interface IHwSearchRebuildService
{
    /**
     * 全量重建搜索索引
     */
    void rebuildAll();
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/IHwSearchService.java

package com.ruoyi.portal.service;

import com.ruoyi.portal.domain.dto.SearchPageDTO;

/**
 * 门户搜索服务
 *
 * @author ruoyi
 */
public interface IHwSearchService
{
    /**
     * 门户搜索
     *
     * @param keyword 关键词
     * @param pageNum 页码
     * @param pageSize 每页条数
     * @return 结果
     */
    SearchPageDTO search(String keyword, Integer pageNum, Integer pageSize);

    /**
     * 编辑端搜索
     *
     * @param keyword 关键词
     * @param pageNum 页码
     * @param pageSize 每页条数
     * @return 结果
     */
    SearchPageDTO searchForEdit(String keyword, Integer pageNum, Integer pageSize);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/IHwWebDocumentService.java

package com.ruoyi.portal.service;

import java.util.List;
import com.ruoyi.portal.domain.HwWebDocument;

/**
 * Hw资料文件Service接口
 * 
 * @author zch
 * @date 2025-09-22
 */
public interface IHwWebDocumentService 
{
    /**
     * 查询Hw资料文件
     * 
     * @param documentId Hw资料文件主键
     * @return Hw资料文件
     */
    public HwWebDocument selectHwWebDocumentByDocumentId(String documentId);

    /**
     * 查询Hw资料文件列表
     * 
     * @param hwWebDocument Hw资料文件
     * @return Hw资料文件集合
     */
    public List<HwWebDocument> selectHwWebDocumentList(HwWebDocument hwWebDocument);

    /**
     * 新增Hw资料文件
     * 
     * @param hwWebDocument Hw资料文件
     * @return 结果
     */
    public int insertHwWebDocument(HwWebDocument hwWebDocument);

    /**
     * 修改Hw资料文件
     * 
     * @param hwWebDocument Hw资料文件
     * @return 结果
     */
    public int updateHwWebDocument(HwWebDocument hwWebDocument);

    /**
     * 批量删除Hw资料文件
     * 
     * @param documentIds 需要删除的Hw资料文件主键集合
     * @return 结果
     */
    public int deleteHwWebDocumentByDocumentIds(String[] documentIds);

    /**
     * 删除Hw资料文件信息
     * 
     * @param documentId Hw资料文件主键
     * @return 结果
     */
    public int deleteHwWebDocumentByDocumentId(String documentId);

        /**
     * 验证密钥并获取文件地址
     * @param documentId 文件ID
     * @param providedKey 提供的密钥
     * @return 文件地址
     * @throws Exception 如果密钥不匹配
     */
    String verifyAndGetDocumentAddress(String documentId, String providedKey) throws Exception;

}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/IHwWebMenuService.java

package com.ruoyi.portal.service;

import java.util.List;
import com.ruoyi.portal.domain.HwWebMenu;

/**
 * haiwei官网菜单Service接口
 * 
 * @author zch
 * @date 2025-08-18
 */
public interface IHwWebMenuService 
{
    /**
     * 查询haiwei官网菜单
     * 
     * @param webMenuId haiwei官网菜单主键
     * @return haiwei官网菜单
     */
    public HwWebMenu selectHwWebMenuByWebMenuId(Long webMenuId);

    /**
     * 查询haiwei官网菜单列表
     * 
     * @param hwWebMenu haiwei官网菜单
     * @return haiwei官网菜单集合
     */
    public List<HwWebMenu> selectHwWebMenuList(HwWebMenu hwWebMenu);

    /**
     * 新增haiwei官网菜单
     * 
     * @param hwWebMenu haiwei官网菜单
     * @return 结果
     */
    public int insertHwWebMenu(HwWebMenu hwWebMenu);

    /**
     * 修改haiwei官网菜单
     * 
     * @param hwWebMenu haiwei官网菜单
     * @return 结果
     */
    public int updateHwWebMenu(HwWebMenu hwWebMenu);

    /**
     * 批量删除haiwei官网菜单
     * 
     * @param webMenuIds 需要删除的haiwei官网菜单主键集合
     * @return 结果
     */
    public int deleteHwWebMenuByWebMenuIds(Long[] webMenuIds);

    /**
     * 删除haiwei官网菜单信息
     * 
     * @param webMenuId haiwei官网菜单主键
     * @return 结果
     */
    public int deleteHwWebMenuByWebMenuId(Long webMenuId);


    /**
     * 获取菜单树列表
     */
    public List<HwWebMenu> selectMenuTree(HwWebMenu hwWebMenu);

}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/IHwWebMenuService1.java

package com.ruoyi.portal.service;

import com.ruoyi.portal.domain.HwWebMenu1;
import com.ruoyi.portal.domain.HwWebMenu1;

import java.util.List;

/**
 * haiwei官网菜单Service接口
 * 
 * @author zch
 * @date 2025-08-18
 */
public interface IHwWebMenuService1
{
    /**
     * 查询haiwei官网菜单
     * 
     * @param webMenuId haiwei官网菜单主键
     * @return haiwei官网菜单
     */
    public HwWebMenu1 selectHwWebMenuByWebMenuId(Long webMenuId);

    /**
     * 查询haiwei官网菜单列表
     * 
     * @param HwWebMenu1 haiwei官网菜单
     * @return haiwei官网菜单集合
     */
    public List<HwWebMenu1> selectHwWebMenuList(HwWebMenu1 HwWebMenu1);

    /**
     * 新增haiwei官网菜单
     * 
     * @param HwWebMenu1 haiwei官网菜单
     * @return 结果
     */
    public int insertHwWebMenu(HwWebMenu1 HwWebMenu1);

    /**
     * 修改haiwei官网菜单
     * 
     * @param HwWebMenu1 haiwei官网菜单
     * @return 结果
     */
    public int updateHwWebMenu(HwWebMenu1 HwWebMenu1);

    /**
     * 批量删除haiwei官网菜单
     * 
     * @param webMenuIds 需要删除的haiwei官网菜单主键集合
     * @return 结果
     */
    public int deleteHwWebMenuByWebMenuIds(Long[] webMenuIds);

    /**
     * 删除haiwei官网菜单信息
     * 
     * @param webMenuId haiwei官网菜单主键
     * @return 结果
     */
    public int deleteHwWebMenuByWebMenuId(Long webMenuId);


    /**
     * 获取菜单树列表
     */
    public List<HwWebMenu1> selectMenuTree(HwWebMenu1 HwWebMenu1);

}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/IHwWebService.java

package com.ruoyi.portal.service;

import java.util.List;
import com.ruoyi.portal.domain.HwWeb;

/**
 * haiwei官网jsonService接口
 * 
 * @author ruoyi
 * @date 2025-08-18
 */
public interface IHwWebService 
{
    /**
     * 查询haiwei官网json
     * 
     * @param webId haiwei官网json主键
     * @return haiwei官网json
     */
    public HwWeb selectHwWebByWebcode(Long webCode);

    /**
     * 查询haiwei官网json列表
     * 
     * @param hwWeb haiwei官网json
     * @return haiwei官网json集合
     */
    public List<HwWeb> selectHwWebList(HwWeb hwWeb);

    /**
     * 新增haiwei官网json
     * 
     * @param hwWeb haiwei官网json
     * @return 结果
     */
    public int insertHwWeb(HwWeb hwWeb);

    /**
     * 修改haiwei官网json
     * 
     * @param hwWeb haiwei官网json
     * @return 结果
     */
    public int updateHwWeb(HwWeb hwWeb);

    /**
     * 批量删除haiwei官网json
     * 
     * @param webIds 需要删除的haiwei官网json主键集合
     * @return 结果
     */
    public int deleteHwWebByWebIds(Long[] webIds);

    /**
     * 删除haiwei官网json信息
     * 
     * @param webId haiwei官网json主键
     * @return 结果
     */
    public int deleteHwWebByWebId(Long webId);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/IHwWebService1.java

package com.ruoyi.portal.service;

import com.ruoyi.portal.domain.HwWeb1;
import java.util.List;

/**
 * haiwei官网jsonService接口
 * 
 * @author ruoyi
 * @date 2025-08-18
 */
public interface IHwWebService1
{
    /**
     * 查询haiwei官网json
     * 
     * @param webId haiwei官网json主键
     * @return haiwei官网json
     */
    public HwWeb1 selectHwWebByWebcode(Long webCode);

    public HwWeb1 selectHwWebOne(HwWeb1 hwWeb1);

    /**
     * 查询haiwei官网json列表
     * 
     * @param HwWeb1 haiwei官网json
     * @return haiwei官网json集合
     */
    public List<HwWeb1> selectHwWebList(HwWeb1 hwWeb1);

    /**
     * 新增haiwei官网json
     * 
     * @param HwWeb1 haiwei官网json
     * @return 结果
     */
    public int insertHwWeb(HwWeb1 hwWeb1);

    /**
     * 修改haiwei官网json
     * 
     * @param HwWeb1 haiwei官网json
     * @return 结果
     */
    public int updateHwWeb(HwWeb1 hwWeb1);

    /**
     * 批量删除haiwei官网json
     * 
     * @param webIds 需要删除的haiwei官网json主键集合
     * @return 结果
     */
    public int deleteHwWebByWebIds(Long[] webIds);

    /**
     * 删除haiwei官网json信息
     * 
     * @param webId haiwei官网json主键
     * @return 结果
     */
    public int deleteHwWebByWebId(Long webId);
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/impl/HwAboutUsInfoDetailServiceImpl.java

package com.ruoyi.portal.service.impl;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.portal.domain.HwAboutUsInfoDetail;
import com.ruoyi.portal.mapper.HwAboutUsInfoDetailMapper;
import com.ruoyi.portal.service.IHwAboutUsInfoDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 关于我们信息明细Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-12-01
 */
@Service
public class HwAboutUsInfoDetailServiceImpl implements IHwAboutUsInfoDetailService 
{
    @Autowired
    private HwAboutUsInfoDetailMapper hwAboutUsInfoDetailMapper;

    /**
     * 查询关于我们信息明细
     * 
     * @param usInfoDetailId 关于我们信息明细主键
     * @return 关于我们信息明细
     */
    @Override
    public HwAboutUsInfoDetail selectHwAboutUsInfoDetailByUsInfoDetailId(Long usInfoDetailId)
    {
        return hwAboutUsInfoDetailMapper.selectHwAboutUsInfoDetailByUsInfoDetailId(usInfoDetailId);
    }

    /**
     * 查询关于我们信息明细列表
     * 
     * @param hwAboutUsInfoDetail 关于我们信息明细
     * @return 关于我们信息明细
     */
    @Override
    public List<HwAboutUsInfoDetail> selectHwAboutUsInfoDetailList(HwAboutUsInfoDetail hwAboutUsInfoDetail)
    {
        return hwAboutUsInfoDetailMapper.selectHwAboutUsInfoDetailList(hwAboutUsInfoDetail);
    }

    /**
     * 新增关于我们信息明细
     * 
     * @param hwAboutUsInfoDetail 关于我们信息明细
     * @return 结果
     */
    @Override
    public int insertHwAboutUsInfoDetail(HwAboutUsInfoDetail hwAboutUsInfoDetail)
    {
        hwAboutUsInfoDetail.setCreateTime(DateUtils.getNowDate());
        return hwAboutUsInfoDetailMapper.insertHwAboutUsInfoDetail(hwAboutUsInfoDetail);
    }

    /**
     * 修改关于我们信息明细
     * 
     * @param hwAboutUsInfoDetail 关于我们信息明细
     * @return 结果
     */
    @Override
    public int updateHwAboutUsInfoDetail(HwAboutUsInfoDetail hwAboutUsInfoDetail)
    {
        hwAboutUsInfoDetail.setUpdateTime(DateUtils.getNowDate());
        return hwAboutUsInfoDetailMapper.updateHwAboutUsInfoDetail(hwAboutUsInfoDetail);
    }

    /**
     * 批量删除关于我们信息明细
     * 
     * @param usInfoDetailIds 需要删除的关于我们信息明细主键
     * @return 结果
     */
    @Override
    public int deleteHwAboutUsInfoDetailByUsInfoDetailIds(Long[] usInfoDetailIds)
    {
        return hwAboutUsInfoDetailMapper.deleteHwAboutUsInfoDetailByUsInfoDetailIds(usInfoDetailIds);
    }

    /**
     * 删除关于我们信息明细信息
     * 
     * @param usInfoDetailId 关于我们信息明细主键
     * @return 结果
     */
    @Override
    public int deleteHwAboutUsInfoDetailByUsInfoDetailId(Long usInfoDetailId)
    {
        return hwAboutUsInfoDetailMapper.deleteHwAboutUsInfoDetailByUsInfoDetailId(usInfoDetailId);
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/impl/HwAboutUsInfoServiceImpl.java

package com.ruoyi.portal.service.impl;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.portal.domain.HwAboutUsInfo;
import com.ruoyi.portal.mapper.HwAboutUsInfoMapper;
import com.ruoyi.portal.service.IHwAboutUsInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 关于我们信息Service业务层处理
 * 
 * @author xins
 * @date 2024-12-01
 */
@Service
public class HwAboutUsInfoServiceImpl implements IHwAboutUsInfoService 
{
    @Autowired
    private HwAboutUsInfoMapper hwAboutUsInfoMapper;

    /**
     * 查询关于我们信息
     * 
     * @param aboutUsInfoId 关于我们信息主键
     * @return 关于我们信息
     */
    @Override
    public HwAboutUsInfo selectHwAboutUsInfoByAboutUsInfoId(Long aboutUsInfoId)
    {
        return hwAboutUsInfoMapper.selectHwAboutUsInfoByAboutUsInfoId(aboutUsInfoId);
    }

    /**
     * 查询关于我们信息列表
     * 
     * @param hwAboutUsInfo 关于我们信息
     * @return 关于我们信息
     */
    @Override
    public List<HwAboutUsInfo> selectHwAboutUsInfoList(HwAboutUsInfo hwAboutUsInfo)
    {
        return hwAboutUsInfoMapper.selectHwAboutUsInfoList(hwAboutUsInfo);
    }

    /**
     * 新增关于我们信息
     * 
     * @param hwAboutUsInfo 关于我们信息
     * @return 结果
     */
    @Override
    public int insertHwAboutUsInfo(HwAboutUsInfo hwAboutUsInfo)
    {
        hwAboutUsInfo.setCreateTime(DateUtils.getNowDate());
        return hwAboutUsInfoMapper.insertHwAboutUsInfo(hwAboutUsInfo);
    }

    /**
     * 修改关于我们信息
     * 
     * @param hwAboutUsInfo 关于我们信息
     * @return 结果
     */
    @Override
    public int updateHwAboutUsInfo(HwAboutUsInfo hwAboutUsInfo)
    {
        hwAboutUsInfo.setUpdateTime(DateUtils.getNowDate());
        return hwAboutUsInfoMapper.updateHwAboutUsInfo(hwAboutUsInfo);
    }

    /**
     * 批量删除关于我们信息
     * 
     * @param aboutUsInfoIds 需要删除的关于我们信息主键
     * @return 结果
     */
    @Override
    public int deleteHwAboutUsInfoByAboutUsInfoIds(Long[] aboutUsInfoIds)
    {
        return hwAboutUsInfoMapper.deleteHwAboutUsInfoByAboutUsInfoIds(aboutUsInfoIds);
    }

    /**
     * 删除关于我们信息信息
     * 
     * @param aboutUsInfoId 关于我们信息主键
     * @return 结果
     */
    @Override
    public int deleteHwAboutUsInfoByAboutUsInfoId(Long aboutUsInfoId)
    {
        return hwAboutUsInfoMapper.deleteHwAboutUsInfoByAboutUsInfoId(aboutUsInfoId);
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/impl/HwAnalyticsServiceImpl.java

package com.ruoyi.portal.service.impl;

import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.UserAgentUtils;
import com.ruoyi.portal.domain.HwWebVisitDaily;
import com.ruoyi.portal.domain.HwWebVisitEvent;
import com.ruoyi.portal.domain.dto.AnalyticsCollectRequest;
import com.ruoyi.portal.domain.dto.AnalyticsDashboardDTO;
import com.ruoyi.portal.domain.dto.AnalyticsRankItemDTO;
import com.ruoyi.portal.mapper.HwAnalyticsMapper;
import com.ruoyi.portal.service.IHwAnalyticsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 官网访问监控服务实现
 *
 * @author ruoyi
 */
@Service
public class HwAnalyticsServiceImpl implements IHwAnalyticsService
{
    private static final Logger log = LoggerFactory.getLogger(HwAnalyticsServiceImpl.class);

    private static final Set<String> ALLOWED_EVENTS = new HashSet<>(Arrays.asList(
            "page_view", "page_leave", "search_submit", "download_click", "contact_submit"
    ));

    private final HwAnalyticsMapper hwAnalyticsMapper;

    public HwAnalyticsServiceImpl(HwAnalyticsMapper hwAnalyticsMapper)
    {
        this.hwAnalyticsMapper = hwAnalyticsMapper;
    }

    @Override
    public void collect(AnalyticsCollectRequest request, String requestIp, String requestUserAgent)
    {
        if (request == null)
        {
            throw new ServiceException("请求体不能为空");
        }
        String eventType = normalizeText(request.getEventType(), 32);
        if (!ALLOWED_EVENTS.contains(eventType))
        {
            throw new ServiceException("不支持的事件类型");
        }

        HwWebVisitEvent event = new HwWebVisitEvent();
        event.setEventType(eventType);
        event.setVisitorId(requireText(request.getVisitorId(), 64, "visitorId不能为空"));
        event.setSessionId(requireText(request.getSessionId(), 64, "sessionId不能为空"));
        event.setPath(requireText(request.getPath(), 500, "path不能为空"));
        event.setReferrer(normalizeText(request.getReferrer(), 500));
        event.setUtmSource(normalizeText(request.getUtmSource(), 128));
        event.setUtmMedium(normalizeText(request.getUtmMedium(), 128));
        event.setUtmCampaign(normalizeText(request.getUtmCampaign(), 128));
        event.setKeyword(normalizeText(request.getKeyword(), 128));
        event.setStayMs(normalizeStayMs(request.getStayMs()));
        event.setEventTime(resolveEventTime(request.getEventTime()));

        String ua = normalizeText(StringUtils.defaultIfBlank(request.getUa(), requestUserAgent), 500);
        event.setUa(ua);
        event.setBrowser(normalizeText(StringUtils.defaultIfBlank(request.getBrowser(), UserAgentUtils.getBrowser(ua)), 64));
        event.setOs(normalizeText(StringUtils.defaultIfBlank(request.getOs(), UserAgentUtils.getOperatingSystem(ua)), 64));
        event.setDevice(normalizeText(StringUtils.defaultIfBlank(request.getDevice(), detectDevice(ua)), 64));

        String ipHash = buildIpHash(requestIp);
        event.setIpHash(ipHash);
        hwAnalyticsMapper.insertVisitEvent(event);

        LocalDate statDate = event.getEventTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        refreshDailyStat(statDate);
    }

    @Override
    public AnalyticsDashboardDTO getDashboard(LocalDate statDate, Integer rankLimit)
    {
        LocalDate targetDate = statDate == null ? LocalDate.now() : statDate;
        int topN = normalizeRankLimit(rankLimit);
        refreshDailyStat(targetDate);

        HwWebVisitDaily daily = hwAnalyticsMapper.selectDailyByDate(targetDate);
        AnalyticsDashboardDTO dashboard = new AnalyticsDashboardDTO();
        dashboard.setStatDate(targetDate.toString());
        dashboard.setPv(daily == null ? 0L : safeLong(daily.getPv()));
        dashboard.setUv(daily == null ? 0L : safeLong(daily.getUv()));
        dashboard.setIpUv(daily == null ? 0L : safeLong(daily.getIpUv()));
        dashboard.setAvgStayMs(daily == null ? 0L : safeLong(daily.getAvgStayMs()));
        dashboard.setBounceRate(daily == null ? 0D : safeDouble(daily.getBounceRate()));
        dashboard.setSearchCount(daily == null ? 0L : safeLong(daily.getSearchCount()));
        dashboard.setDownloadCount(daily == null ? 0L : safeLong(daily.getDownloadCount()));

        List<AnalyticsRankItemDTO> entryPages = hwAnalyticsMapper.selectTopEntryPages(targetDate, topN);
        List<AnalyticsRankItemDTO> hotPages = hwAnalyticsMapper.selectTopHotPages(targetDate, topN);
        List<AnalyticsRankItemDTO> hotKeywords = hwAnalyticsMapper.selectTopKeywords(targetDate, topN);
        dashboard.setEntryPages(entryPages);
        dashboard.setHotPages(hotPages);
        dashboard.setHotKeywords(hotKeywords);
        return dashboard;
    }

    @Override
    public void refreshDailyStat(LocalDate statDate)
    {
        LocalDate targetDate = statDate == null ? LocalDate.now() : statDate;
        Long pv = safeLong(hwAnalyticsMapper.countEventByType(targetDate, "page_view"));
        Long uv = safeLong(hwAnalyticsMapper.countDistinctVisitor(targetDate));
        Long ipUv = safeLong(hwAnalyticsMapper.countDistinctIp(targetDate));
        Long avgStay = safeLong(hwAnalyticsMapper.avgStayMs(targetDate));
        Long searchCount = safeLong(hwAnalyticsMapper.countEventByType(targetDate, "search_submit"));
        Long downloadCount = safeLong(hwAnalyticsMapper.countEventByType(targetDate, "download_click"));
        Long sessionCount = safeLong(hwAnalyticsMapper.countDistinctSessions(targetDate));
        Long singlePageSessionCount = safeLong(hwAnalyticsMapper.countSinglePageSessions(targetDate));

        double bounceRate = 0D;
        if (sessionCount > 0)
        {
            bounceRate = (singlePageSessionCount * 100.0D) / sessionCount;
            bounceRate = Math.round(bounceRate * 100) / 100.0D;
        }

        HwWebVisitDaily daily = new HwWebVisitDaily();
        daily.setStatDate(java.sql.Date.valueOf(targetDate));
        daily.setPv(pv);
        daily.setUv(uv);
        daily.setIpUv(ipUv);
        daily.setAvgStayMs(avgStay);
        daily.setBounceRate(bounceRate);
        daily.setSearchCount(searchCount);
        daily.setDownloadCount(downloadCount);
        hwAnalyticsMapper.upsertDaily(daily);
    }

    private String requireText(String text, int maxLen, String emptyMessage)
    {
        String normalized = normalizeText(text, maxLen);
        if (StringUtils.isBlank(normalized))
        {
            throw new ServiceException(emptyMessage);
        }
        return normalized;
    }

    private String normalizeText(String text, int maxLen)
    {
        String normalized = StringUtils.trim(text);
        if (StringUtils.isBlank(normalized))
        {
            return null;
        }
        if (normalized.length() > maxLen)
        {
            normalized = normalized.substring(0, maxLen);
        }
        return normalized;
    }

    private Long normalizeStayMs(Long stayMs)
    {
        if (stayMs == null)
        {
            return null;
        }
        if (stayMs < 0)
        {
            return 0L;
        }
        return Math.min(stayMs, 7L * 24 * 3600 * 1000);
    }

    private Date resolveEventTime(Long timestamp)
    {
        if (timestamp == null || timestamp <= 0)
        {
            return new Date();
        }
        try
        {
            return Date.from(Instant.ofEpochMilli(timestamp));
        }
        catch (Exception e)
        {
            log.warn("invalid eventTime: {}", timestamp);
            return new Date();
        }
    }

    private String detectDevice(String ua)
    {
        String text = StringUtils.defaultString(ua).toLowerCase();
        if (text.contains("ipad") || text.contains("tablet"))
        {
            return "Tablet";
        }
        if (text.contains("mobile") || text.contains("android") || text.contains("iphone"))
        {
            return "Mobile";
        }
        return "Desktop";
    }

    private String buildIpHash(String ip)
    {
        String safeIp = StringUtils.defaultIfBlank(ip, "unknown");
        try
        {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest((safeIp + "|hw-portal-analytics").getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte b : hash)
            {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        }
        catch (Exception e)
        {
            return Integer.toHexString(safeIp.hashCode());
        }
    }

    private int normalizeRankLimit(Integer rankLimit)
    {
        if (rankLimit == null || rankLimit <= 0)
        {
            return 10;
        }
        return Math.min(rankLimit, 50);
    }

    private long safeLong(Long value)
    {
        return value == null ? 0L : value;
    }

    private double safeDouble(Double value)
    {
        return value == null ? 0D : value;
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/impl/HwContactUsInfoServiceImpl.java

package com.ruoyi.portal.service.impl;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.portal.domain.HwContactUsInfo;
import com.ruoyi.portal.mapper.HwContactUsInfoMapper;
import com.ruoyi.portal.service.IHwContactUsInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 联系我们信息Service业务层处理
 * 
 * @author xins
 * @date 2024-12-01
 */
@Service
public class HwContactUsInfoServiceImpl implements IHwContactUsInfoService 
{
    @Autowired
    private HwContactUsInfoMapper hwContactUsInfoMapper;

    /**
     * 查询联系我们信息
     * 
     * @param contactUsInfoId 联系我们信息主键
     * @return 联系我们信息
     */
    @Override
    public HwContactUsInfo selectHwContactUsInfoByContactUsInfoId(Long contactUsInfoId)
    {
        return hwContactUsInfoMapper.selectHwContactUsInfoByContactUsInfoId(contactUsInfoId);
    }

    /**
     * 查询联系我们信息列表
     * 
     * @param hwContactUsInfo 联系我们信息
     * @return 联系我们信息
     */
    @Override
    public List<HwContactUsInfo> selectHwContactUsInfoList(HwContactUsInfo hwContactUsInfo)
    {
        return hwContactUsInfoMapper.selectHwContactUsInfoList(hwContactUsInfo);
    }

    /**
     * 新增联系我们信息
     * 
     * @param hwContactUsInfo 联系我们信息
     * @return 结果
     */
    @Override
    public int insertHwContactUsInfo(HwContactUsInfo hwContactUsInfo)
    {

        hwContactUsInfo.setCreateTime(DateUtils.getNowDate());
        return hwContactUsInfoMapper.insertHwContactUsInfo(hwContactUsInfo);
    }

    /**
     * 修改联系我们信息
     * 
     * @param hwContactUsInfo 联系我们信息
     * @return 结果
     */
    @Override
    public int updateHwContactUsInfo(HwContactUsInfo hwContactUsInfo)
    {
        hwContactUsInfo.setUpdateTime(DateUtils.getNowDate());
        return hwContactUsInfoMapper.updateHwContactUsInfo(hwContactUsInfo);
    }

    /**
     * 批量删除联系我们信息
     * 
     * @param contactUsInfoIds 需要删除的联系我们信息主键
     * @return 结果
     */
    @Override
    public int deleteHwContactUsInfoByContactUsInfoIds(Long[] contactUsInfoIds)
    {
        return hwContactUsInfoMapper.deleteHwContactUsInfoByContactUsInfoIds(contactUsInfoIds);
    }

    /**
     * 删除联系我们信息信息
     * 
     * @param contactUsInfoId 联系我们信息主键
     * @return 结果
     */
    @Override
    public int deleteHwContactUsInfoByContactUsInfoId(Long contactUsInfoId)
    {
        return hwContactUsInfoMapper.deleteHwContactUsInfoByContactUsInfoId(contactUsInfoId);
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/impl/HwPortalConfigServiceImpl.java

package com.ruoyi.portal.service.impl;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.portal.domain.HwPortalConfig;
import com.ruoyi.portal.mapper.HwPortalConfigMapper;
import com.ruoyi.portal.service.IHwPortalConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 门户网站配置Service业务层处理
 * 
 * @author xins
 * @date 2024-12-01
 */
@Service
public class HwPortalConfigServiceImpl implements IHwPortalConfigService 
{
    @Autowired
    private HwPortalConfigMapper hwPortalConfigMapper;

    /**
     * 查询门户网站配置
     * 
     * @param portalConfigId 门户网站配置主键
     * @return 门户网站配置
     */
    @Override
    public HwPortalConfig selectHwPortalConfigByPortalConfigId(Long portalConfigId)
    {
        return hwPortalConfigMapper.selectHwPortalConfigByPortalConfigId(portalConfigId);
    }

    /**
     * 查询门户网站配置列表
     * 
     * @param hwPortalConfig 门户网站配置
     * @return 门户网站配置
     */
    @Override
    public List<HwPortalConfig> selectHwPortalConfigList(HwPortalConfig hwPortalConfig)
    {
        if("2".equals(hwPortalConfig.getPortalConfigType())){
            List<HwPortalConfig> hwPortalConfigs = hwPortalConfigMapper.selectHwPortalConfigList2(hwPortalConfig);
            return hwPortalConfigs;
        }
        return hwPortalConfigMapper.selectHwPortalConfigList(hwPortalConfig);
    }

    /**
     * 新增门户网站配置
     * 
     * @param hwPortalConfig 门户网站配置
     * @return 结果
     */
    @Override
    public int insertHwPortalConfig(HwPortalConfig hwPortalConfig)
    {
        hwPortalConfig.setCreateTime(DateUtils.getNowDate());
        return hwPortalConfigMapper.insertHwPortalConfig(hwPortalConfig);
    }

    /**
     * 修改门户网站配置
     * 
     * @param hwPortalConfig 门户网站配置
     * @return 结果
     */
    @Override
    public int updateHwPortalConfig(HwPortalConfig hwPortalConfig)
    {
        hwPortalConfig.setUpdateTime(DateUtils.getNowDate());
        return hwPortalConfigMapper.updateHwPortalConfig(hwPortalConfig);
    }

    /**
     * 批量删除门户网站配置
     * 
     * @param portalConfigIds 需要删除的门户网站配置主键
     * @return 结果
     */
    @Override
    public int deleteHwPortalConfigByPortalConfigIds(Long[] portalConfigIds)
    {
        return hwPortalConfigMapper.deleteHwPortalConfigByPortalConfigIds(portalConfigIds);
    }

    /**
     * 删除门户网站配置信息
     * 
     * @param portalConfigId 门户网站配置主键
     * @return 结果
     */
    @Override
    public int deleteHwPortalConfigByPortalConfigId(Long portalConfigId)
    {
        return hwPortalConfigMapper.deleteHwPortalConfigByPortalConfigId(portalConfigId);
    }



    /**
     * 查询门户网站配置列表,Join hw_portal_config_type
     *
     * @param hwPortalConfig 门户网站配置
     * @return 门户网站配置
     */
    @Override
    public List<HwPortalConfig> selectHwPortalConfigJoinList(HwPortalConfig hwPortalConfig)
    {
        return hwPortalConfigMapper.selectHwPortalConfigJoinList(hwPortalConfig);
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/impl/HwPortalConfigTypeServiceImpl.java

package com.ruoyi.portal.service.impl;

import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.portal.domain.HwPortalConfigType;
import com.ruoyi.portal.domain.vo.TreeSelect;
import com.ruoyi.portal.mapper.HwPortalConfigTypeMapper;
import com.ruoyi.portal.service.IHwPortalConfigTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 门户网站配置类型Service业务层处理
 * 
 * @author xins
 * @date 2024-12-11
 */
@Service
public class HwPortalConfigTypeServiceImpl implements IHwPortalConfigTypeService 
{
    @Autowired
    private HwPortalConfigTypeMapper hwPortalConfigTypeMapper;

    /**
     * 查询门户网站配置类型
     * 
     * @param configTypeId 门户网站配置类型主键
     * @return 门户网站配置类型
     */
    @Override
    public HwPortalConfigType selectHwPortalConfigTypeByConfigTypeId(Long configTypeId)
    {
        return hwPortalConfigTypeMapper.selectHwPortalConfigTypeByConfigTypeId(configTypeId);
    }

    /**
     * 查询门户网站配置类型列表
     * 
     * @param hwPortalConfigType 门户网站配置类型
     * @return 门户网站配置类型
     */
     @Override
     public List<HwPortalConfigType> selectHwPortalConfigTypeList(HwPortalConfigType hwPortalConfigType)
     {
         return hwPortalConfigTypeMapper.selectHwPortalConfigTypeList(hwPortalConfigType);
     }


    /**
     * 查询门户网站配置类型列表
     * 
     * @param hwPortalConfigType 门户网站配置类型
     * @return 门户网站配置类型
     */
    @Override
    public List<HwPortalConfigType> selectConfigTypeList(HwPortalConfigType hwPortalConfigType)
    {
        // 如果有 configTypeClassfication 条件,需要特殊处理以确保树形结构完整
        if (StringUtils.isNotEmpty(hwPortalConfigType.getConfigTypeClassfication())) {
            // 查询所有数据
            List<HwPortalConfigType> allList = hwPortalConfigTypeMapper.selectHwPortalConfigTypeList(new HwPortalConfigType());
            
            // 找出指定分类的顶级节点
            List<HwPortalConfigType> topLevelNodes = allList.stream()
                .filter(item -> hwPortalConfigType.getConfigTypeClassfication().equals(item.getConfigTypeClassfication()) 
                              && (item.getParentId() == null || item.getParentId() == 0L))
                .collect(Collectors.toList());
            
            // 构建包含所有子孙节点的完整列表
            List<HwPortalConfigType> completeList = new ArrayList<>();
            for (HwPortalConfigType topNode : topLevelNodes) {
                completeList.add(topNode);
                addAllDescendants(allList, topNode, completeList);
            }
            
            return buildPortalConfigTypeTree(completeList);
        } else {
            // 没有特定过滤条件时,直接查询并构建树形结构
            List<HwPortalConfigType> list = hwPortalConfigTypeMapper.selectHwPortalConfigTypeList(hwPortalConfigType);
            return buildPortalConfigTypeTree(list);
        }
    }

    /**
     * 递归添加所有子孙节点
     */
    private void addAllDescendants(List<HwPortalConfigType> allList, HwPortalConfigType parentNode, List<HwPortalConfigType> resultList) {
        for (HwPortalConfigType item : allList) {
            if (item.getParentId() != null && item.getParentId().equals(parentNode.getConfigTypeId())) {
                resultList.add(item);
                addAllDescendants(allList, item, resultList); // 递归添加子节点的子节点
            }
        }
    }

    /**
     * 新增门户网站配置类型
     * 
     * @param hwPortalConfigType 门户网站配置类型
     * @return 结果
     */
    @Override
    public int insertHwPortalConfigType(HwPortalConfigType hwPortalConfigType)
    {
        if (hwPortalConfigType.getParentId() == null) {
            hwPortalConfigType.setParentId(0L);
            hwPortalConfigType.setAncestors("0");
        } else {
            HwPortalConfigType info = hwPortalConfigTypeMapper.selectHwPortalConfigTypeByConfigTypeId(hwPortalConfigType.getParentId());

            hwPortalConfigType.setAncestors(info.getAncestors() + "," + hwPortalConfigType.getParentId());
        }

        hwPortalConfigType.setCreateTime(DateUtils.getNowDate());
        hwPortalConfigType.setCreateBy(SecurityUtils.getUsername());
        return hwPortalConfigTypeMapper.insertHwPortalConfigType(hwPortalConfigType);
    }

    /**
     * 修改门户网站配置类型
     * 
     * @param hwPortalConfigType 门户网站配置类型
     * @return 结果
     */
    @Override
    public int updateHwPortalConfigType(HwPortalConfigType hwPortalConfigType)
    {
        hwPortalConfigType.setUpdateTime(DateUtils.getNowDate());
        return hwPortalConfigTypeMapper.updateHwPortalConfigType(hwPortalConfigType);
    }

    /**
     * 批量删除门户网站配置类型
     * 
     * @param configTypeIds 需要删除的门户网站配置类型主键
     * @return 结果
     */
    @Override
    public int deleteHwPortalConfigTypeByConfigTypeIds(Long[] configTypeIds)
    {
        return hwPortalConfigTypeMapper.deleteHwPortalConfigTypeByConfigTypeIds(configTypeIds);
    }

    /**
     * 删除门户网站配置类型信息
     * 
     * @param configTypeId 门户网站配置类型主键
     * @return 结果
     */
    @Override
    public int deleteHwPortalConfigTypeByConfigTypeId(Long configTypeId)
    {
        return hwPortalConfigTypeMapper.deleteHwPortalConfigTypeByConfigTypeId(configTypeId);
    }


    /**
     * 查询门户网站配置类型树结构信息
     *
     * @param portalConfigType 门户网站配置类型信息
     * @return 门户网站配置类型树信息集合
     */
    @Override
    public List<TreeSelect> selectPortalConfigTypeTreeList(HwPortalConfigType portalConfigType) {
        List<HwPortalConfigType> portalConfigTypes = this.selectHwPortalConfigTypeList(portalConfigType);
        return buildPortalConfigTypeTreeSelect(portalConfigTypes);
    }

    /**
     * 构建前端所需要下拉树结构
     *
     * @param portalConfigTypes 门户网站配置类型列表
     * @return 下拉树结构列表
     */
    @Override
    public List<TreeSelect> buildPortalConfigTypeTreeSelect(List<HwPortalConfigType> portalConfigTypes) {
        List<HwPortalConfigType> deptTrees = buildPortalConfigTypeTree(portalConfigTypes);
        return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }


    /**
     * 构建前端所需要树结构
     *
     * @param portalConfigTypes 门户网站配置类型列表
     * @return 树结构列表
     */
    @Override
    public List<HwPortalConfigType> buildPortalConfigTypeTree(List<HwPortalConfigType> portalConfigTypes) {
        List<HwPortalConfigType> returnList = new ArrayList<HwPortalConfigType>();
        List<Long> tempList = portalConfigTypes.stream().map(HwPortalConfigType::getConfigTypeId).collect(Collectors.toList());
        for (HwPortalConfigType portalConfigType : portalConfigTypes) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(portalConfigType.getParentId())) {
                recursionFn(portalConfigTypes, portalConfigType);
                returnList.add(portalConfigType);
            }
        }
        if (returnList.isEmpty()) {
            returnList = portalConfigTypes;
        }
        return returnList;
    }


    /**
     * 递归列表
     */
    private void recursionFn(List<HwPortalConfigType> list, HwPortalConfigType t) {
        // 得到子节点列表
        List<HwPortalConfigType> childList = getChildList(list, t);
        t.setChildren(childList);
        for (HwPortalConfigType tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<HwPortalConfigType> getChildList(List<HwPortalConfigType> list, HwPortalConfigType t) {
        List<HwPortalConfigType> tlist = new ArrayList<HwPortalConfigType>();
        Iterator<HwPortalConfigType> it = list.iterator();
        while (it.hasNext()) {
            HwPortalConfigType n = (HwPortalConfigType) it.next();
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getConfigTypeId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<HwPortalConfigType> list, HwPortalConfigType t) {
        return getChildList(list, t).size() > 0 ? true : false;
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/impl/HwProductCaseInfoServiceImpl.java

package com.ruoyi.portal.service.impl;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.portal.domain.HwProductCaseInfo;
import com.ruoyi.portal.mapper.HwProductCaseInfoMapper;
import com.ruoyi.portal.service.IHwProductCaseInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 案例内容Service业务层处理
 * 
 * @author xins
 * @date 2024-12-01
 */
@Service
public class HwProductCaseInfoServiceImpl implements IHwProductCaseInfoService 
{
    @Autowired
    private HwProductCaseInfoMapper hwProductCaseInfoMapper;

    /**
     * 查询案例内容
     * 
     * @param caseInfoId 案例内容主键
     * @return 案例内容
     */
    @Override
    public HwProductCaseInfo selectHwProductCaseInfoByCaseInfoId(Long caseInfoId)
    {
        return hwProductCaseInfoMapper.selectHwProductCaseInfoByCaseInfoId(caseInfoId);
    }

    /**
     * 查询案例内容列表
     * 
     * @param hwProductCaseInfo 案例内容
     * @return 案例内容
     */
    @Override
    public List<HwProductCaseInfo> selectHwProductCaseInfoList(HwProductCaseInfo hwProductCaseInfo)
    {
        return hwProductCaseInfoMapper.selectHwProductCaseInfoList(hwProductCaseInfo);
    }

    /**
     * 新增案例内容
     * 
     * @param hwProductCaseInfo 案例内容
     * @return 结果
     */
    @Override
    public int insertHwProductCaseInfo(HwProductCaseInfo hwProductCaseInfo)
    {
        hwProductCaseInfo.setCreateTime(DateUtils.getNowDate());
        return hwProductCaseInfoMapper.insertHwProductCaseInfo(hwProductCaseInfo);
    }

    /**
     * 修改案例内容
     * 
     * @param hwProductCaseInfo 案例内容
     * @return 结果
     */
    @Override
    public int updateHwProductCaseInfo(HwProductCaseInfo hwProductCaseInfo)
    {
        hwProductCaseInfo.setUpdateTime(DateUtils.getNowDate());
        return hwProductCaseInfoMapper.updateHwProductCaseInfo(hwProductCaseInfo);
    }

    /**
     * 批量删除案例内容
     * 
     * @param caseInfoIds 需要删除的案例内容主键
     * @return 结果
     */
    @Override
    public int deleteHwProductCaseInfoByCaseInfoIds(Long[] caseInfoIds)
    {
        return hwProductCaseInfoMapper.deleteHwProductCaseInfoByCaseInfoIds(caseInfoIds);
    }

    /**
     * 删除案例内容信息
     * 
     * @param caseInfoId 案例内容主键
     * @return 结果
     */
    @Override
    public int deleteHwProductCaseInfoByCaseInfoId(Long caseInfoId)
    {
        return hwProductCaseInfoMapper.deleteHwProductCaseInfoByCaseInfoId(caseInfoId);
    }

    /**
     * 根据configTypeId获取首页典型案例
     * @param hwProductCaseInfo
     * @return
     */
    @Override
    public HwProductCaseInfo getTypicalHomeCaseInfo(HwProductCaseInfo hwProductCaseInfo){
        hwProductCaseInfo.setHomeTypicalFlag("1");
        List<HwProductCaseInfo> productCaseInfoList = hwProductCaseInfoMapper.selectHwProductCaseInfoList(hwProductCaseInfo);
        List<HwProductCaseInfo> typicalProductCaseInfoList = productCaseInfoList.stream().filter(pci -> pci.getTypicalFlag().equals("1")).collect(Collectors.toList());
        if(typicalProductCaseInfoList!=null && ! typicalProductCaseInfoList.isEmpty()){
            return typicalProductCaseInfoList.get(0);
        }else if (productCaseInfoList!=null && !productCaseInfoList.isEmpty()){
            return productCaseInfoList.get(0);
        }
        return new HwProductCaseInfo();
    }


    /**
     * 查询案例内容列表,join portalConfigType
     *
     * @param hwProductCaseInfo 案例内容
     * @return 案例内容
     */
    @Override
    public List<HwProductCaseInfo> selectHwProductCaseInfoJoinList(HwProductCaseInfo hwProductCaseInfo)
    {
        return hwProductCaseInfoMapper.selectHwProductCaseInfoJoinList(hwProductCaseInfo);
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/impl/HwProductInfoDetailServiceImpl.java

package com.ruoyi.portal.service.impl;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.portal.domain.HwPortalConfigType;
import com.ruoyi.portal.domain.HwProductInfoDetail;
import com.ruoyi.portal.mapper.HwProductInfoDetailMapper;
import com.ruoyi.portal.service.IHwProductInfoDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 产品信息明细配置Service业务层处理
 * 
 * @author xins
 * @date 2024-12-11
 */
@Service
public class HwProductInfoDetailServiceImpl implements IHwProductInfoDetailService 
{
    @Autowired
    private HwProductInfoDetailMapper hwProductInfoDetailMapper;

    /**
     * 查询产品信息明细配置
     * 
     * @param productInfoDetailId 产品信息明细配置主键
     * @return 产品信息明细配置
     */
    @Override
    public HwProductInfoDetail selectHwProductInfoDetailByProductInfoDetailId(Long productInfoDetailId)
    {
        return hwProductInfoDetailMapper.selectHwProductInfoDetailByProductInfoDetailId(productInfoDetailId);
    }

    /**
     * 查询产品信息明细配置列表
     * 
     * @param hwProductInfoDetail 产品信息明细配置
     * @return 产品信息明细配置
     */
    @Override
    public List<HwProductInfoDetail> selectHwProductInfoDetailList(HwProductInfoDetail hwProductInfoDetail)
    {
        return hwProductInfoDetailMapper.selectHwProductInfoDetailList(hwProductInfoDetail);
    }

    /**
     * 新增产品信息明细配置
     *
     * @param hwProductInfoDetail 产品信息明细配置
     * @return 结果
     */
    @Override
    public int insertHwProductInfoDetail(HwProductInfoDetail hwProductInfoDetail)
    {
        if (hwProductInfoDetail.getParentId() == null) {
            hwProductInfoDetail.setParentId(0L);
            hwProductInfoDetail.setAncestors("0");
        }else if(hwProductInfoDetail.getParentId() == 0L) {
            hwProductInfoDetail.setParentId(0L);
            hwProductInfoDetail.setAncestors("0");
        } else {
            HwProductInfoDetail info = hwProductInfoDetailMapper.selectHwProductInfoDetailByProductInfoDetailId(hwProductInfoDetail.getParentId());

            hwProductInfoDetail.setAncestors(info.getAncestors() + "," + hwProductInfoDetail.getParentId());
        }

        hwProductInfoDetail.setCreateTime(DateUtils.getNowDate());
        hwProductInfoDetail.setCreateBy(SecurityUtils.getUsername());

        return hwProductInfoDetailMapper.insertHwProductInfoDetail(hwProductInfoDetail);
    }

    /**
     * 修改产品信息明细配置
     * 
     * @param hwProductInfoDetail 产品信息明细配置
     * @return 结果
     */
    @Override
    public int updateHwProductInfoDetail(HwProductInfoDetail hwProductInfoDetail)
    {
        hwProductInfoDetail.setUpdateTime(DateUtils.getNowDate());
        return hwProductInfoDetailMapper.updateHwProductInfoDetail(hwProductInfoDetail);
    }

    /**
     * 批量删除产品信息明细配置
     * 
     * @param productInfoDetailIds 需要删除的产品信息明细配置主键
     * @return 结果
     */
    @Override
    public int deleteHwProductInfoDetailByProductInfoDetailIds(Long[] productInfoDetailIds)
    {
        return hwProductInfoDetailMapper.deleteHwProductInfoDetailByProductInfoDetailIds(productInfoDetailIds);
    }

    /**
     * 删除产品信息明细配置信息
     * 
     * @param productInfoDetailId 产品信息明细配置主键
     * @return 结果
     */
    @Override
    public int deleteHwProductInfoDetailByProductInfoDetailId(Long productInfoDetailId)
    {
        return hwProductInfoDetailMapper.deleteHwProductInfoDetailByProductInfoDetailId(productInfoDetailId);
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/impl/HwProductInfoServiceImpl.java

package com.ruoyi.portal.service.impl;

import com.ruoyi.common.constant.HwPortalConstants;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.portal.domain.HwProductInfo;
import com.ruoyi.portal.domain.HwProductInfoDetail;
import com.ruoyi.portal.mapper.HwProductInfoMapper;
import com.ruoyi.portal.service.IHwProductInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 产品信息配置Service业务层处理
 * 
 * @author xins
 * @date 2024-12-01
 */
@Service
public class HwProductInfoServiceImpl implements IHwProductInfoService 
{
    @Autowired
    private HwProductInfoMapper hwProductInfoMapper;

    /**
     * 查询产品信息配置
     * 
     * @param productInfoId 产品信息配置主键
     * @return 产品信息配置
     */
    @Override
    public HwProductInfo selectHwProductInfoByProductInfoId(Long productInfoId)
    {
        return hwProductInfoMapper.selectHwProductInfoByProductInfoId(productInfoId);
    }

    /**
     * 查询产品信息配置列表
     * 
     * @param hwProductInfo 产品信息配置
     * @return 产品信息配置
     */
    @Override
    public List<HwProductInfo> selectHwProductInfoList(HwProductInfo hwProductInfo)
    {
        return hwProductInfoMapper.selectHwProductInfoList(hwProductInfo);
    }

    /**
     * 新增产品信息配置
     * 
     * @param hwProductInfo 产品信息配置
     * @return 结果
     */
    @Override
    public int insertHwProductInfo(HwProductInfo hwProductInfo)
    {
        hwProductInfo.setCreateTime(DateUtils.getNowDate());
        return hwProductInfoMapper.insertHwProductInfo(hwProductInfo);
    }

    /**
     * 修改产品信息配置
     * 
     * @param hwProductInfo 产品信息配置
     * @return 结果
     */
    @Override
    public int updateHwProductInfo(HwProductInfo hwProductInfo)
    {
        hwProductInfo.setUpdateTime(DateUtils.getNowDate());
        return hwProductInfoMapper.updateHwProductInfo(hwProductInfo);
    }

    /**
     * 批量删除产品信息配置
     * 
     * @param productInfoIds 需要删除的产品信息配置主键
     * @return 结果
     */
    @Override
    public int deleteHwProductInfoByProductInfoIds(Long[] productInfoIds)
    {
        return hwProductInfoMapper.deleteHwProductInfoByProductInfoIds(productInfoIds);
    }

    /**
     * 删除产品信息配置信息
     * 
     * @param productInfoId 产品信息配置主键
     * @return 结果
     */
    @Override
    public int deleteHwProductInfoByProductInfoId(Long productInfoId)
    {
        return hwProductInfoMapper.deleteHwProductInfoByProductInfoId(productInfoId);
    }


    /**
     * 获取产品中心产品信息(平台简介,hw_product_info获取配置模式2左标题+内容右图片读取中文标题和英文标题下面内容从hw_product_info_detail获取读取标题内容和图片)
     *
     * @param hwProductInfo 产品信息配置
     * @return 产品信息配置
     */
    @Override
    public List<HwProductInfo> selectHwProductInfoJoinDetailList(HwProductInfo hwProductInfo)
    {
        List<HwProductInfo> hwProductInfoJoinDetailList =  hwProductInfoMapper.selectHwProductInfoJoinDetailList(hwProductInfo);
        
        // 若配置模式configModal为13hwProductInfoDetailList应该变为树形结构
        if ("13".equals(hwProductInfo.getConfigModal())) {
            for (HwProductInfo productInfo : hwProductInfoJoinDetailList) {
                if (productInfo.getHwProductInfoDetailList() != null && !productInfo.getHwProductInfoDetailList().isEmpty()) {
                    // 将每个产品信息的明细列表转换为树形结构
                    List<HwProductInfoDetail> treeStructureList = buildProductInfoDetailTree(productInfo.getHwProductInfoDetailList());
                    productInfo.setHwProductInfoDetailList(treeStructureList);
                }
            }
        }

        for (HwProductInfo productInfo : hwProductInfoJoinDetailList) {
            List<HwProductInfoDetail> hwProductInfoDetailList = productInfo.getHwProductInfoDetailList();
            for (HwProductInfoDetail hwProductInfoDetail : hwProductInfoDetailList) {
                if ("13".equals(hwProductInfoDetail.getConfigModel())){
                    // 将每个产品信息的明细列表转换为树形结构
                    List<HwProductInfoDetail> treeStructureList = buildProductInfoDetailTree(productInfo.getHwProductInfoDetailList());
                    productInfo.setHwProductInfoDetailList(treeStructureList);
                }
            }
        }
        
        return hwProductInfoJoinDetailList;
    }



    /**
     * 构建前端所需要树结构
     *
     * @param productInfoDetails 产品明细列表
     * @return 树结构列表
     */
    public List<HwProductInfoDetail> buildProductInfoDetailTree(List<HwProductInfoDetail> productInfoDetails) {
        List<HwProductInfoDetail> returnList = new ArrayList<>();
        List<Long> tempList = productInfoDetails.stream().map(HwProductInfoDetail::getProductInfoDetailId).collect(Collectors.toList());
        for (HwProductInfoDetail hwProductInfoDetail : productInfoDetails) {
/*            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(hwProductInfoDetail.getParentId())) {*/
            // 如果是顶级节点(parentId为null、0或者不在当前列表中), 遍历该父节点的所有子节点
            if (hwProductInfoDetail.getParentId() == null || hwProductInfoDetail.getParentId() == 0L || !tempList.contains(hwProductInfoDetail.getParentId())) {
                recursionFn(productInfoDetails, hwProductInfoDetail);
                returnList.add(hwProductInfoDetail);
            }
        }
        if (returnList.isEmpty()) {
            returnList = productInfoDetails;
        }
        return returnList;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<HwProductInfoDetail> list, HwProductInfoDetail t) {
        // 得到子节点列表
        List<HwProductInfoDetail> childList = getChildList(list, t);
        // 设置TreeEntity的children字段
        t.setChildren(childList);
        // 设置HwProductInfoDetail的hwProductInfoDetailList字段
        t.setHwProductInfoDetailList(childList);
        
        for (HwProductInfoDetail tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }


    /**
     * 得到子节点列表
     */
    private List<HwProductInfoDetail> getChildList(List<HwProductInfoDetail> list, HwProductInfoDetail t) {
        List<HwProductInfoDetail> tlist = new ArrayList<HwProductInfoDetail>();
        Iterator<HwProductInfoDetail> it = list.iterator();
        while (it.hasNext()) {
            HwProductInfoDetail n = (HwProductInfoDetail) it.next();
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getProductInfoDetailId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<HwProductInfoDetail> list, HwProductInfoDetail t) {
        return getChildList(list, t).size() > 0 ? true : false;
    }


    /**
     * 查询产品信息配置列表,join portalConfigType
     *
     * @param hwProductInfo 产品信息配置
     * @return 产品信息配置
     */
    @Override
    public List<HwProductInfo> selectHwProductInfoJoinList(HwProductInfo hwProductInfo)
    {
        return hwProductInfoMapper.selectHwProductInfoJoinList(hwProductInfo);
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/impl/HwSearchRebuildServiceImpl.java

package com.ruoyi.portal.service.impl;

import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.portal.domain.HwPortalConfigType;
import com.ruoyi.portal.domain.HwWeb;
import com.ruoyi.portal.domain.HwWeb1;
import com.ruoyi.portal.domain.HwWebDocument;
import com.ruoyi.portal.domain.HwWebMenu;
import com.ruoyi.portal.mapper.HwPortalConfigTypeMapper;
import com.ruoyi.portal.mapper.HwWebDocumentMapper;
import com.ruoyi.portal.mapper.HwWebMapper;
import com.ruoyi.portal.mapper.HwWebMapper1;
import com.ruoyi.portal.mapper.HwWebMenuMapper;
import com.ruoyi.portal.search.convert.PortalSearchDocConverter;
import com.ruoyi.portal.search.es.entity.PortalSearchDoc;
import com.ruoyi.portal.search.es.mapper.PortalSearchMapper;
import com.ruoyi.portal.service.IHwSearchRebuildService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 搜索索引重建实现
 *
 * @author ruoyi
 */
@Service
public class HwSearchRebuildServiceImpl implements IHwSearchRebuildService
{
    private static final Logger log = LoggerFactory.getLogger(HwSearchRebuildServiceImpl.class);

    private static final String INDEX_NAME = "hw_portal_content";

    private final PortalSearchMapper portalSearchMapper;

    private final PortalSearchDocConverter converter;

    private final HwWebMenuMapper hwWebMenuMapper;

    private final HwWebMapper hwWebMapper;

    private final HwWebMapper1 hwWebMapper1;

    private final HwWebDocumentMapper hwWebDocumentMapper;

    private final HwPortalConfigTypeMapper hwPortalConfigTypeMapper;

    public HwSearchRebuildServiceImpl(PortalSearchMapper portalSearchMapper, PortalSearchDocConverter converter,
                                      HwWebMenuMapper hwWebMenuMapper, HwWebMapper hwWebMapper, HwWebMapper1 hwWebMapper1,
                                      HwWebDocumentMapper hwWebDocumentMapper, HwPortalConfigTypeMapper hwPortalConfigTypeMapper)
    {
        this.portalSearchMapper = portalSearchMapper;
        this.converter = converter;
        this.hwWebMenuMapper = hwWebMenuMapper;
        this.hwWebMapper = hwWebMapper;
        this.hwWebMapper1 = hwWebMapper1;
        this.hwWebDocumentMapper = hwWebDocumentMapper;
        this.hwPortalConfigTypeMapper = hwPortalConfigTypeMapper;
    }

    @Override
    public void rebuildAll()
    {
        try
        {
            if (portalSearchMapper.existsIndex(INDEX_NAME))
            {
                portalSearchMapper.deleteIndex(INDEX_NAME);
            }
            portalSearchMapper.createIndex();

            List<PortalSearchDoc> docs = collectDocs();
            if (!docs.isEmpty())
            {
                portalSearchMapper.insertBatch(docs);
            }
            log.info("rebuild search index finished. docs={}", docs.size());
        }
        catch (Exception e)
        {
            throw new ServiceException("重建搜索索引失败: " + e.getMessage());
        }
    }

    private List<PortalSearchDoc> collectDocs()
    {
        List<PortalSearchDoc> docs = new ArrayList<>();
        List<HwWebMenu> menus = hwWebMenuMapper.selectHwWebMenuList(new HwWebMenu());
        menus.forEach(item -> docs.add(converter.fromWebMenu(item)));

        List<HwWeb> webs = hwWebMapper.selectHwWebList(new HwWeb());
        webs.forEach(item -> docs.add(converter.fromWeb(item)));

        List<HwWeb1> web1List = hwWebMapper1.selectHwWebList(new HwWeb1());
        web1List.forEach(item -> docs.add(converter.fromWeb1(item)));

        List<HwWebDocument> documents = hwWebDocumentMapper.selectHwWebDocumentList(new HwWebDocument());
        documents.forEach(item -> docs.add(converter.fromDocument(item)));

        List<HwPortalConfigType> configTypes = hwPortalConfigTypeMapper.selectHwPortalConfigTypeList(new HwPortalConfigType());
        configTypes.forEach(item -> docs.add(converter.fromConfigType(item)));
        return docs;
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/impl/HwSearchServiceImpl.java

package com.ruoyi.portal.service.impl;

import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.portal.domain.dto.SearchPageDTO;
import com.ruoyi.portal.domain.dto.SearchRawRecord;
import com.ruoyi.portal.domain.dto.SearchResultDTO;
import com.ruoyi.portal.mapper.HwSearchMapper;
import com.ruoyi.portal.search.convert.PortalSearchDocConverter;
import com.ruoyi.portal.search.service.PortalSearchEsService;
import com.ruoyi.portal.service.IHwSearchService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 门户搜索服务实现
 *
 * @author ruoyi
 */
@Service
public class HwSearchServiceImpl implements IHwSearchService
{
    private static final Logger log = LoggerFactory.getLogger(HwSearchServiceImpl.class);

    private static final Pattern ESCAPE_PATTERN = Pattern.compile("([\\\\.*+\\[\\](){}^$?|])");

    private final HwSearchMapper hwSearchMapper;

    private final PortalSearchDocConverter converter;

    private final PortalSearchEsService portalSearchEsService;

    @Value("${search.engine:mysql}")
    private String searchEngine;

    @Value("${search.es.enabled:false}")
    private boolean esEnabled;

    public HwSearchServiceImpl(HwSearchMapper hwSearchMapper, PortalSearchDocConverter converter,
                               @Autowired(required = false) PortalSearchEsService portalSearchEsService)
    {
        this.hwSearchMapper = hwSearchMapper;
        this.converter = converter;
        this.portalSearchEsService = portalSearchEsService;
    }

    @Override
    public SearchPageDTO search(String keyword, Integer pageNum, Integer pageSize)
    {
        return doSearch(keyword, pageNum, pageSize, false);
    }

    @Override
    public SearchPageDTO searchForEdit(String keyword, Integer pageNum, Integer pageSize)
    {
        return doSearch(keyword, pageNum, pageSize, true);
    }

    private SearchPageDTO doSearch(String keyword, Integer pageNum, Integer pageSize, boolean editMode)
    {
        String normalizedKeyword = validateKeyword(keyword);
        int normalizedPageNum = normalizePageNum(pageNum);
        int normalizedPageSize = normalizePageSize(pageSize);

        if (useEsEngine())
        {
            try
            {
                return portalSearchEsService.search(normalizedKeyword, normalizedPageNum, normalizedPageSize, editMode);
            }
            catch (Exception e)
            {
                log.error("ES search failed, fallback to mysql. keyword={}", normalizedKeyword, e);
            }
        }
        return searchByMysql(normalizedKeyword, normalizedPageNum, normalizedPageSize, editMode);
    }

    private boolean useEsEngine()
    {
        return esEnabled && portalSearchEsService != null && "es".equalsIgnoreCase(searchEngine);
    }

    private SearchPageDTO searchByMysql(String keyword, int pageNum, int pageSize, boolean editMode)
    {
        List<SearchRawRecord> rawRecords = hwSearchMapper.searchByKeyword(keyword);
        if (rawRecords == null || rawRecords.isEmpty())
        {
            return new SearchPageDTO();
        }

        List<SearchResultDTO> all = new ArrayList<>();
        for (SearchRawRecord raw : rawRecords)
        {
            SearchResultDTO dto = toResult(raw, keyword, editMode);
            if (dto != null)
            {
                all.add(dto);
            }
        }
        all = all.stream().sorted(Comparator.comparing(SearchResultDTO::getScore).reversed()).collect(Collectors.toList());

        SearchPageDTO page = new SearchPageDTO();
        page.setTotal(all.size());
        int from = Math.max(0, (pageNum - 1) * pageSize);
        if (from >= all.size())
        {
            page.setRows(new ArrayList<>());
            return page;
        }
        int to = Math.min(all.size(), from + pageSize);
        page.setRows(all.subList(from, to));
        return page;
    }

    private SearchResultDTO toResult(SearchRawRecord raw, String keyword, boolean editMode)
    {
        String sourceType = raw.getSourceType();
        String content = StringUtils.defaultString(raw.getContent());
        if (PortalSearchDocConverter.SOURCE_WEB.equals(sourceType) || PortalSearchDocConverter.SOURCE_WEB1.equals(sourceType))
        {
            content = converter.extractSearchableText(content);
            if (!containsIgnoreCase(raw.getTitle(), keyword) && !containsIgnoreCase(content, keyword))
            {
                return null;
            }
        }
        else if (!containsIgnoreCase(raw.getTitle(), keyword) && !containsIgnoreCase(content, keyword))
        {
            return null;
        }

        SearchResultDTO dto = new SearchResultDTO();
        dto.setSourceType(sourceType);
        dto.setTitle(raw.getTitle());
        dto.setSnippet(buildSnippet(raw.getTitle(), content, keyword));
        dto.setScore(calculateScore(raw, keyword));
        dto.setRoute(buildRoute(sourceType, raw.getWebCode()));
        dto.setRouteQuery(buildRouteQuery(raw));
        if (editMode)
        {
            dto.setEditRoute(buildEditRoute(raw));
        }
        return dto;
    }

    private int calculateScore(SearchRawRecord raw, String keyword)
    {
        int base = raw.getScore() == null ? 0 : raw.getScore();
        String title = StringUtils.defaultString(raw.getTitle());
        String content = StringUtils.defaultString(raw.getContent());
        if (containsIgnoreCase(title, keyword))
        {
            base += 20;
        }
        if (containsIgnoreCase(content, keyword))
        {
            base += 10;
        }
        return base;
    }

    private String buildRoute(String sourceType, String webCode)
    {
        if (PortalSearchDocConverter.SOURCE_MENU.equals(sourceType))
        {
            return "/test";
        }
        if (PortalSearchDocConverter.SOURCE_WEB.equals(sourceType))
        {
            if ("-1".equals(webCode))
            {
                return "/index";
            }
            if ("7".equals(webCode))
            {
                return "/productCenter";
            }
            return "/test";
        }
        if (PortalSearchDocConverter.SOURCE_WEB1.equals(sourceType))
        {
            return "/productCenter/detail";
        }
        if (PortalSearchDocConverter.SOURCE_DOCUMENT.equals(sourceType))
        {
            return "/serviceSupport";
        }
        if (PortalSearchDocConverter.SOURCE_CONFIG_TYPE.equals(sourceType))
        {
            return "/productCenter";
        }
        return "/index";
    }

    private Map<String, Object> buildRouteQuery(SearchRawRecord raw)
    {
        Map<String, Object> query = new HashMap<>();
        String sourceType = raw.getSourceType();
        if (PortalSearchDocConverter.SOURCE_MENU.equals(sourceType))
        {
            query.put("id", raw.getMenuId());
            return query;
        }
        if (PortalSearchDocConverter.SOURCE_WEB.equals(sourceType) && !"-1".equals(raw.getWebCode()) && !"7".equals(raw.getWebCode()))
        {
            query.put("id", raw.getWebCode());
            return query;
        }
        if (PortalSearchDocConverter.SOURCE_WEB1.equals(sourceType))
        {
            query.put("webCode", raw.getWebCode());
            query.put("typeId", raw.getTypeId());
            query.put("deviceId", raw.getDeviceId());
            return query;
        }
        if (PortalSearchDocConverter.SOURCE_DOCUMENT.equals(sourceType))
        {
            query.put("documentId", raw.getDocumentId());
            query.put("webCode", raw.getWebCode());
            query.put("typeId", raw.getTypeId());
            return query;
        }
        if (PortalSearchDocConverter.SOURCE_CONFIG_TYPE.equals(sourceType))
        {
            query.put("configTypeId", raw.getTypeId());
            return query;
        }
        return query;
    }

    private String buildEditRoute(SearchRawRecord raw)
    {
        String sourceType = raw.getSourceType();
        if (PortalSearchDocConverter.SOURCE_MENU.equals(sourceType))
        {
            return "/editor?type=1&id=" + raw.getMenuId();
        }
        if (PortalSearchDocConverter.SOURCE_WEB.equals(sourceType))
        {
            if ("7".equals(raw.getWebCode()))
            {
                return "/productCenter/edit";
            }
            if ("-1".equals(raw.getWebCode()))
            {
                return "/editor?type=3&id=-1";
            }
            return "/editor?type=1&id=" + raw.getWebCode();
        }
        if (PortalSearchDocConverter.SOURCE_WEB1.equals(sourceType))
        {
            return "/editor?type=2&id=" + raw.getWebCode() + "," + raw.getTypeId() + "," + raw.getDeviceId();
        }
        if (PortalSearchDocConverter.SOURCE_DOCUMENT.equals(sourceType))
        {
            if (StringUtils.isNotBlank(raw.getWebCode()) && StringUtils.isNotBlank(raw.getTypeId()) && StringUtils.isNotBlank(raw.getDeviceId()))
            {
                return "/editor?type=2&id=" + raw.getWebCode() + "," + raw.getTypeId() + "," + raw.getDeviceId() + "&documentId=" + raw.getDocumentId();
            }
            return "/editor?type=2&documentId=" + raw.getDocumentId();
        }
        if (PortalSearchDocConverter.SOURCE_CONFIG_TYPE.equals(sourceType))
        {
            return "/productCenter/edit";
        }
        return "/editor";
    }

    private String buildSnippet(String title, String content, String keyword)
    {
        if (StringUtils.isNotBlank(title) && containsIgnoreCase(title, keyword))
        {
            return highlight(title, keyword);
        }
        if (StringUtils.isBlank(content))
        {
            return StringUtils.EMPTY;
        }
        String normalized = content.replaceAll("\\s+", " ").trim();
        int index = StringUtils.indexOfIgnoreCase(normalized, keyword);
        if (index < 0)
        {
            return StringUtils.substring(normalized, 0, Math.min(120, normalized.length()));
        }
        int start = Math.max(0, index - 60);
        int end = Math.min(normalized.length(), index + keyword.length() + 60);
        String snippet = normalized.substring(start, end);
        if (start > 0)
        {
            snippet = "..." + snippet;
        }
        if (end < normalized.length())
        {
            snippet = snippet + "...";
        }
        return highlight(snippet, keyword);
    }

    private String highlight(String text, String keyword)
    {
        if (StringUtils.isBlank(text) || StringUtils.isBlank(keyword))
        {
            return StringUtils.defaultString(text);
        }
        String escaped = ESCAPE_PATTERN.matcher(keyword).replaceAll("\\\\$1");
        Matcher matcher = Pattern.compile("(?i)" + escaped).matcher(text);
        if (!matcher.find())
        {
            return text;
        }
        return matcher.replaceAll("<em class=\"search-hit\">$0</em>");
    }

    private boolean containsIgnoreCase(String text, String keyword)
    {
        return StringUtils.isNotBlank(text) && StringUtils.isNotBlank(keyword) && StringUtils.containsIgnoreCase(text, keyword);
    }

    private int normalizePageNum(Integer pageNum)
    {
        if (pageNum == null || pageNum <= 0)
        {
            return 1;
        }
        return pageNum;
    }

    private int normalizePageSize(Integer pageSize)
    {
        if (pageSize == null || pageSize <= 0)
        {
            return 20;
        }
        return Math.min(pageSize, 50);
    }

    private String validateKeyword(String keyword)
    {
        String normalized = StringUtils.trim(keyword);
        if (StringUtils.isBlank(normalized))
        {
            throw new ServiceException("关键词不能为空");
        }
        if (normalized.length() > 50)
        {
            throw new ServiceException("关键词长度不能超过50");
        }
        return normalized;
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/impl/HwWebDocumentServiceImpl.java

package com.ruoyi.portal.service.impl;

import java.util.List;

import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.portal.mapper.HwWebDocumentMapper;
import com.ruoyi.portal.domain.HwWebDocument;
import com.ruoyi.portal.service.IHwSearchRebuildService;
import com.ruoyi.portal.service.IHwWebDocumentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Hw资料文件Service业务层处理
 * 
 * @author zch
 * @date 2025-09-22
 */
@Service
public class HwWebDocumentServiceImpl implements IHwWebDocumentService 
{
    private static final Logger log = LoggerFactory.getLogger(HwWebDocumentServiceImpl.class);

    @Autowired
    private HwWebDocumentMapper hwWebDocumentMapper;

    @Autowired(required = false)
    private IHwSearchRebuildService hwSearchRebuildService;

    /**
     * 查询Hw资料文件
     * 
     * @param documentId Hw资料文件主键
     * @return Hw资料文件
     */
    @Override
    public HwWebDocument selectHwWebDocumentByDocumentId(String documentId)
    {
        return hwWebDocumentMapper.selectHwWebDocumentByDocumentId(documentId);
    }

    /**
     * 查询Hw资料文件列表
     * 
     * @param hwWebDocument Hw资料文件
     * @return Hw资料文件
     */
    @Override
    public List<HwWebDocument> selectHwWebDocumentList(HwWebDocument hwWebDocument)
    {
        return hwWebDocumentMapper.selectHwWebDocumentList(hwWebDocument);
    }

    /**
     * 新增Hw资料文件
     * 
     * @param hwWebDocument Hw资料文件
     * @return 结果
     */
    @Override
    public int insertHwWebDocument(HwWebDocument hwWebDocument)
    {
        hwWebDocument.setCreateTime(DateUtils.getNowDate());
        int rows = hwWebDocumentMapper.insertHwWebDocument(hwWebDocument);
        if (rows > 0)
        {
            rebuildSearchIndexQuietly();
        }
        return rows;
    }

    /**
     * 修改Hw资料文件
     * 
     * @param hwWebDocument Hw资料文件
     * @return 结果
     */
    @Override
    public int updateHwWebDocument(HwWebDocument hwWebDocument)
    {
        // 特殊处理 secretKey前端不传或传 null 时清空数据库密钥
        // 将 null 转换为空字符串,触发 Mapper 更新条件
        if (hwWebDocument.getSecretKey() == null) {
            hwWebDocument.setSecretKey("");
        }
        
        int rows = hwWebDocumentMapper.updateHwWebDocument(hwWebDocument);
        if (rows > 0)
        {
            rebuildSearchIndexQuietly();
        }
        return rows;
    }

    /**
     * 批量删除Hw资料文件
     * 
     * @param documentIds 需要删除的Hw资料文件主键
     * @return 结果
     */
    @Override
    public int deleteHwWebDocumentByDocumentIds(String[] documentIds)
    {
        int rows = hwWebDocumentMapper.deleteHwWebDocumentByDocumentIds(documentIds);
        if (rows > 0)
        {
            rebuildSearchIndexQuietly();
        }
        return rows;
    }

    /**
     * 删除Hw资料文件信息
     * 
     * @param documentId Hw资料文件主键
     * @return 结果
     */
    @Override
    public int deleteHwWebDocumentByDocumentId(String documentId)
    {
        int rows = hwWebDocumentMapper.deleteHwWebDocumentByDocumentId(documentId);
        if (rows > 0)
        {
            rebuildSearchIndexQuietly();
        }
        return rows;
    }

    @Override
    public String verifyAndGetDocumentAddress(String documentId, String providedKey) throws Exception {
        HwWebDocument document = selectHwWebDocumentByDocumentId(documentId);
        if (document == null) {
            throw new ServiceException("文件不存在");
        }
        String secretKey = document.getSecretKey();
        String address = document.getDocumentAddress();
        
        // 若数据库密钥为空,则直接返回文件地址
        if (secretKey == null || secretKey.trim().isEmpty()) {
            return address;
        }
        
        // 若密钥不为空,则需要验证提供的密钥是否相等
        String trimmedProvided = providedKey == null ? null : providedKey.trim();
        if (trimmedProvided == null || trimmedProvided.isEmpty()) {
            throw new ServiceException("密钥不能为空");
        }
        
        if (secretKey.trim().equals(trimmedProvided)) {
            return address;
        } else {
            throw new ServiceException("密钥错误");
        }
    }

    private void rebuildSearchIndexQuietly()
    {
        if (hwSearchRebuildService == null)
        {
            return;
        }
        try
        {
            hwSearchRebuildService.rebuildAll();
        }
        catch (Exception e)
        {
            log.error("rebuild portal search index failed after hw_web_document changed", e);
        }
    }


}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/impl/HwWebMenuServiceImpl.java

package com.ruoyi.portal.service.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.portal.domain.HwProductInfoDetail;
import com.ruoyi.portal.service.IHwSearchRebuildService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.portal.mapper.HwWebMenuMapper;
import com.ruoyi.portal.domain.HwWebMenu;
import com.ruoyi.portal.service.IHwWebMenuService;

/**
 * haiwei官网菜单Service业务层处理
 *
 * @author zch
 * @date 2025-08-18
 */
@Service
public class HwWebMenuServiceImpl implements IHwWebMenuService
{
    private static final Logger log = LoggerFactory.getLogger(HwWebMenuServiceImpl.class);

    @Autowired
    private HwWebMenuMapper hwWebMenuMapper;

    @Autowired(required = false)
    private IHwSearchRebuildService hwSearchRebuildService;

    /**
     * 查询haiwei官网菜单
     *
     * @param webMenuId haiwei官网菜单主键
     * @return haiwei官网菜单
     */
    @Override
    public HwWebMenu selectHwWebMenuByWebMenuId(Long webMenuId)
    {
        return hwWebMenuMapper.selectHwWebMenuByWebMenuId(webMenuId);
    }

    /**
     * 查询haiwei官网菜单列表
     *
     * @param hwWebMenu haiwei官网菜单
     * @return haiwei官网菜单
     */
    @Override
    public List<HwWebMenu> selectHwWebMenuList(HwWebMenu hwWebMenu)
    {
        List<HwWebMenu> hwWebMenus = hwWebMenuMapper.selectHwWebMenuList(hwWebMenu);
        return hwWebMenus;
    }

    /**
     * 获取菜单树列表
     */
    @Override
    public List<HwWebMenu> selectMenuTree(HwWebMenu hwWebMenu)
    {
        List<HwWebMenu> hwWebMenus = hwWebMenuMapper.selectHwWebMenuList(hwWebMenu);
        return buildWebMenuTree(hwWebMenus);
    }

    /**
     * 新增haiwei官网菜单
     *
     * @param hwWebMenu haiwei官网菜单
     * @return 结果
     */
    @Override
    public int insertHwWebMenu(HwWebMenu hwWebMenu)
    {
        int rows = hwWebMenuMapper.insertHwWebMenu(hwWebMenu);
        if (rows > 0)
        {
            rebuildSearchIndexQuietly();
        }
        return rows;
    }

    /**
     * 修改haiwei官网菜单
     *
     * @param hwWebMenu haiwei官网菜单
     * @return 结果
     */
    @Override
    public int updateHwWebMenu(HwWebMenu hwWebMenu)
    {
        int rows = hwWebMenuMapper.updateHwWebMenu(hwWebMenu);
        if (rows > 0)
        {
            rebuildSearchIndexQuietly();
        }
        return rows;
    }

    /**
     * 批量删除haiwei官网菜单
     *
     * @param webMenuIds 需要删除的haiwei官网菜单主键
     * @return 结果
     */
    @Override
    public int deleteHwWebMenuByWebMenuIds(Long[] webMenuIds)
    {
        int rows = hwWebMenuMapper.deleteHwWebMenuByWebMenuIds(webMenuIds);
        if (rows > 0)
        {
            rebuildSearchIndexQuietly();
        }
        return rows;
    }

    /**
     * 删除haiwei官网菜单信息
     *
     * @param webMenuId haiwei官网菜单主键
     * @return 结果
     */
    @Override
    public int deleteHwWebMenuByWebMenuId(Long webMenuId)
    {
        int rows = hwWebMenuMapper.deleteHwWebMenuByWebMenuId(webMenuId);
        if (rows > 0)
        {
            rebuildSearchIndexQuietly();
        }
        return rows;
    }

/**
     * 构建前端所需要树结构(根据传入的平铺菜单列表构造树)
     *
     * @param menus 菜单列表
     * @return 树结构列表
     */
    public List<HwWebMenu> buildWebMenuTree(List<HwWebMenu> menus) {
        List<HwWebMenu> returnList = new ArrayList<>();
        List<Long> tempList = menus.stream().map(HwWebMenu::getWebMenuId).collect(Collectors.toList());
        for (HwWebMenu menu : menus) {
            // 如果是顶级节点(parent为null、0或者不在当前列表中), 遍历该父节点的所有子节点
            if (menu.getParent() == null || menu.getParent() == 0L || !tempList.contains(menu.getParent())) {
                recursionFn(menus, menu);
                returnList.add(menu);
            }
        }
        if (returnList.isEmpty()) {
            returnList = menus;
        }
        return returnList;
    }

    /**
     * 递归设置子节点
     */
    private void recursionFn(List<HwWebMenu> list, HwWebMenu t) {
        // 得到子节点列表
        List<HwWebMenu> childList = getChildList(list, t);
        t.setChildren(childList);
        for (HwWebMenu tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<HwWebMenu> getChildList(List<HwWebMenu> list, HwWebMenu t) {
        List<HwWebMenu> tlist = new ArrayList<HwWebMenu>();
        Iterator<HwWebMenu> it = list.iterator();
        while (it.hasNext()) {
            HwWebMenu n = it.next();
            if (StringUtils.isNotNull(n.getParent()) && n.getParent().longValue() == t.getWebMenuId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<HwWebMenu> list, HwWebMenu t) {
        return !getChildList(list, t).isEmpty();
    }

    private void rebuildSearchIndexQuietly()
    {
        if (hwSearchRebuildService == null)
        {
            return;
        }
        try
        {
            hwSearchRebuildService.rebuildAll();
        }
        catch (Exception e)
        {
            log.error("rebuild portal search index failed after hw_web_menu changed", e);
        }
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/impl/HwWebMenuServiceImpl1.java

package com.ruoyi.portal.service.impl;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.portal.domain.HwWebMenu1;
import com.ruoyi.portal.mapper.HwWebMenuMapper1;
import com.ruoyi.portal.service.IHwWebMenuService1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * haiwei官网菜单Service业务层处理
 *
 * @author zch
 * @date 2025-08-18
 */
@Service
public class HwWebMenuServiceImpl1 implements IHwWebMenuService1
{
    @Autowired
    private HwWebMenuMapper1 HwWebMenuMapper1;

    /**
     * 查询haiwei官网菜单
     *
     * @param webMenuId haiwei官网菜单主键
     * @return haiwei官网菜单
     */
    @Override
    public HwWebMenu1 selectHwWebMenuByWebMenuId(Long webMenuId)
    {
        return HwWebMenuMapper1.selectHwWebMenuByWebMenuId(webMenuId);
    }

    /**
     * 查询haiwei官网菜单列表
     *
     * @param HwWebMenu1 haiwei官网菜单
     * @return haiwei官网菜单
     */
    @Override
    public List<HwWebMenu1> selectHwWebMenuList(HwWebMenu1 HwWebMenu1)
    {
        List<HwWebMenu1> hwWebMenus = HwWebMenuMapper1.selectHwWebMenuList(HwWebMenu1);
        return hwWebMenus;
    }

    /**
     * 获取菜单树列表
     */
    @Override
    public List<HwWebMenu1> selectMenuTree(HwWebMenu1 HwWebMenu1)
    {
        List<HwWebMenu1> hwWebMenus = HwWebMenuMapper1.selectHwWebMenuList(HwWebMenu1);
        return buildWebMenuTree(hwWebMenus);
    }

    /**
     * 新增haiwei官网菜单
     *
     * @param HwWebMenu1 haiwei官网菜单
     * @return 结果
     */
    @Override
    public int insertHwWebMenu(HwWebMenu1 HwWebMenu1)
    {
        return HwWebMenuMapper1.insertHwWebMenu(HwWebMenu1);
    }

    /**
     * 修改haiwei官网菜单
     *
     * @param HwWebMenu1 haiwei官网菜单
     * @return 结果
     */
    @Override
    public int updateHwWebMenu(HwWebMenu1 HwWebMenu1)
    {
        return HwWebMenuMapper1.updateHwWebMenu(HwWebMenu1);
    }

    /**
     * 批量删除haiwei官网菜单
     *
     * @param webMenuIds 需要删除的haiwei官网菜单主键
     * @return 结果
     */
    @Override
    public int deleteHwWebMenuByWebMenuIds(Long[] webMenuIds)
    {
        return HwWebMenuMapper1.deleteHwWebMenuByWebMenuIds(webMenuIds);
    }

    /**
     * 删除haiwei官网菜单信息
     *
     * @param webMenuId haiwei官网菜单主键
     * @return 结果
     */
    @Override
    public int deleteHwWebMenuByWebMenuId(Long webMenuId)
    {
        return HwWebMenuMapper1.deleteHwWebMenuByWebMenuId(webMenuId);
    }

/**
     * 构建前端所需要树结构(根据传入的平铺菜单列表构造树)
     *
     * @param menus 菜单列表
     * @return 树结构列表
     */
    public List<HwWebMenu1> buildWebMenuTree(List<HwWebMenu1> menus) {
        List<HwWebMenu1> returnList = new ArrayList<>();
        List<Long> tempList = menus.stream().map(HwWebMenu1::getWebMenuId).collect(Collectors.toList());
        for (HwWebMenu1 menu : menus) {
            // 如果是顶级节点(parent为null、0或者不在当前列表中), 遍历该父节点的所有子节点
            if (menu.getParent() == null || menu.getParent() == 0L || !tempList.contains(menu.getParent())) {
                recursionFn(menus, menu);
                returnList.add(menu);
            }
        }
        if (returnList.isEmpty()) {
            returnList = menus;
        }
        return returnList;
    }

    /**
     * 递归设置子节点
     */
    private void recursionFn(List<HwWebMenu1> list, HwWebMenu1 t) {
        // 得到子节点列表
        List<HwWebMenu1> childList = getChildList(list, t);
        t.setChildren(childList);
        for (HwWebMenu1 tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<HwWebMenu1> getChildList(List<HwWebMenu1> list, HwWebMenu1 t) {
        List<HwWebMenu1> tlist = new ArrayList<HwWebMenu1>();
        Iterator<HwWebMenu1> it = list.iterator();
        while (it.hasNext()) {
            HwWebMenu1 n = it.next();
            if (StringUtils.isNotNull(n.getParent()) && n.getParent().longValue() == t.getWebMenuId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<HwWebMenu1> list, HwWebMenu1 t) {
        return !getChildList(list, t).isEmpty();
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/impl/HwWebServiceImpl.java

package com.ruoyi.portal.service.impl;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.portal.mapper.HwWebMapper;
import com.ruoyi.portal.domain.HwWeb;
import com.ruoyi.portal.service.IHwWebService;
import com.ruoyi.portal.service.IHwSearchRebuildService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

/**
 * haiwei官网jsonService业务层处理
 * 
 * @author ruoyi
 * @date 2025-08-18
 */
@Service
public class HwWebServiceImpl implements IHwWebService 
{
    private static final Logger log = LoggerFactory.getLogger(HwWebServiceImpl.class);

    @Autowired
    private HwWebMapper hwWebMapper;

    @Autowired(required = false)
    private IHwSearchRebuildService hwSearchRebuildService;

    /**
     * 查询haiwei官网json
     * 
     * @param webId haiwei官网json主键
     * @return haiwei官网json
     */
    @Override
    public HwWeb selectHwWebByWebcode(Long webCode)
    {
        HwWeb hwWeb = hwWebMapper.selectHwWebByWebcode(webCode);
        return hwWeb;
    }


    /**
     * 查询haiwei官网json列表
     * 
     * @param hwWeb haiwei官网json
     * @return haiwei官网json
     */
    @Override
    public List<HwWeb> selectHwWebList(HwWeb hwWeb)
    {
        return hwWebMapper.selectHwWebList(hwWeb);
    }

    /**
     * 新增haiwei官网json
     * 
     * @param hwWeb haiwei官网json
     * @return 结果
     */
    @Override
    public int insertHwWeb(HwWeb hwWeb)
    {
        int rows = hwWebMapper.insertHwWeb(hwWeb);
        if (rows > 0)
        {
            rebuildSearchIndexQuietly();
        }
        return rows;
    }

    /**
     * 修改haiwei官网json
     * 
     * @param hwWeb haiwei官网json
     * @return 结果
     */
    @Override
    @Transactional( rollbackFor = Exception.class )
    public int updateHwWeb(HwWeb hwWeb)
    {
        HwWeb codeWeb = new HwWeb();
        //编号唯一
        codeWeb.setWebCode(hwWeb.getWebCode());
        List<HwWeb> exists = hwWebMapper.selectHwWebList(codeWeb);
        if (!exists.isEmpty()) {
            Long[] webIds = exists.stream().map(HwWeb::getWebId).toArray(Long[]::new);
            //逻辑删除旧纪录
            hwWebMapper.deleteHwWebByWebIds(webIds);
        }
        // 插入新记录,避免复用旧主键
        // hwWeb.setWebId(null);
        hwWeb.setIsDelete("0");
        int rows = hwWebMapper.insertHwWeb(hwWeb);
        if (rows > 0)
        {
            rebuildSearchIndexQuietly();
        }
        return rows;
    }

    /**
     * 批量删除haiwei官网json
     * 
     * @param webIds 需要删除的haiwei官网json主键
     * @return 结果
     */
    @Override
    public int deleteHwWebByWebIds(Long[] webIds)
    {
        int rows = hwWebMapper.deleteHwWebByWebIds(webIds);
        if (rows > 0)
        {
            rebuildSearchIndexQuietly();
        }
        return rows;
    }

    /**
     * 删除haiwei官网json信息
     * 
     * @param webId haiwei官网json主键
     * @return 结果
     */
    @Override
    public int deleteHwWebByWebId(Long webId)
    {
        int rows = hwWebMapper.deleteHwWebByWebId(webId);
        if (rows > 0)
        {
            rebuildSearchIndexQuietly();
        }
        return rows;
    }

    private void rebuildSearchIndexQuietly()
    {
        if (hwSearchRebuildService == null)
        {
            return;
        }
        try
        {
            hwSearchRebuildService.rebuildAll();
        }
        catch (Exception e)
        {
            log.error("rebuild portal search index failed after hw_web changed", e);
        }
    }
}

ruoyi-portal/src/main/java/com/ruoyi/portal/service/impl/HwWebServiceImpl1.java

package com.ruoyi.portal.service.impl;


import com.ruoyi.portal.mapper.HwWebMapper1;
import com.ruoyi.portal.service.IHwSearchRebuildService;
import com.ruoyi.portal.service.IHwWebService1;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import com.ruoyi.portal.domain.HwWeb1;
import com.ruoyi.portal.domain.HwWeb;
import org.springframework.transaction.annotation.Transactional;

/**
 * haiwei官网jsonService业务层处理
 * 
 * @author ruoyi
 * @date 2025-08-18
 */
@Service
public class HwWebServiceImpl1 implements IHwWebService1
{
    private static final Logger log = LoggerFactory.getLogger(HwWebServiceImpl1.class);

    @Autowired
    private HwWebMapper1 hwWebMapper1;

    @Autowired(required = false)
    private IHwSearchRebuildService hwSearchRebuildService;

    /**
     * 查询haiwei官网json
     * 
     * @param webId haiwei官网json主键
     * @return haiwei官网json
     */
    @Override
    public HwWeb1 selectHwWebByWebcode(Long webCode)
    {
        return hwWebMapper1.selectHwWebByWebcode(webCode);
    }

    @Override
    public HwWeb1 selectHwWebOne(HwWeb1 hwWeb1)
    {
        return hwWebMapper1.selectHwWebOne(hwWeb1);
    }


    /**
     * 查询haiwei官网json列表
     * 
     * @param HwWeb1 haiwei官网json
     * @return haiwei官网json
     */
    @Override
    public List<HwWeb1> selectHwWebList(HwWeb1 hwWeb1)
    {
        return hwWebMapper1.selectHwWebList(hwWeb1);
    }

    /**
     * 新增haiwei官网json
     * 
     * @param HwWeb1 haiwei官网json
     * @return 结果
     */
    @Override
    public int insertHwWeb(HwWeb1 hwWeb1)
    {
        int rows = hwWebMapper1.insertHwWeb(hwWeb1);
        if (rows > 0)
        {
            rebuildSearchIndexQuietly();
        }
        return rows;
    }

    /**
     * 修改haiwei官网json
     * 
     * @param HwWeb1 haiwei官网json
     * @return 结果
     */
    @Override
    @Transactional( rollbackFor = Exception.class )
    public int updateHwWeb(HwWeb1 hwWeb1)
    {
        HwWeb1 codeWeb = new HwWeb1();
        // 编号、typeid、deviceID保证唯一
        codeWeb.setWebCode(hwWeb1.getWebCode());
        codeWeb.setTypeId(hwWeb1.getTypeId());
        codeWeb.setDeviceId(hwWeb1.getDeviceId());
        List<HwWeb1> exists = hwWebMapper1.selectHwWebList(codeWeb);
        if (!exists.isEmpty()) {
            Long[] webIds = exists.stream().map(HwWeb1::getWebId).toArray(Long[]::new);
            //逻辑删除旧纪录
            hwWebMapper1.deleteHwWebByWebIds(webIds);
        }
        // 插入新记录,避免复用旧主键
        // hwWeb1.setWebId(null);
        hwWeb1.setIsDelete("0");
        int rows = hwWebMapper1.insertHwWeb(hwWeb1);
        if (rows > 0)
        {
            rebuildSearchIndexQuietly();
        }
        return rows;
    }

    /**
     * 批量删除haiwei官网json
     * 
     * @param webIds 需要删除的haiwei官网json主键
     * @return 结果
     */
    @Override
    public int deleteHwWebByWebIds(Long[] webIds)
    {
        int rows = hwWebMapper1.deleteHwWebByWebIds(webIds);
        if (rows > 0)
        {
            rebuildSearchIndexQuietly();
        }
        return rows;
    }

    /**
     * 删除haiwei官网json信息
     * 
     * @param webId haiwei官网json主键
     * @return 结果
     */
    @Override
    public int deleteHwWebByWebId(Long webId)
    {
        int rows = hwWebMapper1.deleteHwWebByWebId(webId);
        if (rows > 0)
        {
            rebuildSearchIndexQuietly();
        }
        return rows;
    }

    private void rebuildSearchIndexQuietly()
    {
        if (hwSearchRebuildService == null)
        {
            return;
        }
        try
        {
            hwSearchRebuildService.rebuildAll();
        }
        catch (Exception e)
        {
            log.error("rebuild portal search index failed after hw_web1 changed", e);
        }
    }
}

ruoyi-portal/src/main/resources/mapper/portal/HwAboutUsInfoDetailMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.portal.mapper.HwAboutUsInfoDetailMapper">
    
    <resultMap type="HwAboutUsInfoDetail" id="HwAboutUsInfoDetailResult">
        <result property="usInfoDetailId"    column="us_info_detail_id"    />
        <result property="aboutUsInfoId"    column="about_us_info_id"    />
        <result property="usInfoDetailTitle"    column="us_info_detail_title"    />
        <result property="usInfoDetailDesc"    column="us_info_detail_desc"    />
        <result property="usInfoDetailOrder"    column="us_info_detail_order"    />
        <result property="usInfoDetailPic"    column="us_info_detail_pic"    />
        <result property="createTime"    column="create_time"    />
        <result property="createBy"    column="create_by"    />
        <result property="updateTime"    column="update_time"    />
        <result property="updateBy"    column="update_by"    />
    </resultMap>

    <sql id="selectHwAboutUsInfoDetailVo">
        select us_info_detail_id, about_us_info_id, us_info_detail_title, us_info_detail_desc, us_info_detail_order, us_info_detail_pic, create_time, create_by, update_time, update_by from hw_about_us_info_detail
    </sql>

    <select id="selectHwAboutUsInfoDetailList" parameterType="HwAboutUsInfoDetail" resultMap="HwAboutUsInfoDetailResult">
        <include refid="selectHwAboutUsInfoDetailVo"/>
        <where>  
            <if test="aboutUsInfoId != null "> and about_us_info_id = #{aboutUsInfoId}</if>
            <if test="usInfoDetailTitle != null  and usInfoDetailTitle != ''"> and us_info_detail_title like concat('%', #{usInfoDetailTitle}, '%')</if>
            <if test="usInfoDetailDesc != null  and usInfoDetailDesc != ''"> and us_info_detail_desc like concat('%', #{usInfoDetailDesc}, '%')</if>
            <if test="usInfoDetailOrder != null "> and us_info_detail_order = #{usInfoDetailOrder}</if>
            <if test="usInfoDetailPic != null  and usInfoDetailPic != ''"> and us_info_detail_pic = #{usInfoDetailPic}</if>
        </where>
    </select>
    
    <select id="selectHwAboutUsInfoDetailByUsInfoDetailId" parameterType="Long" resultMap="HwAboutUsInfoDetailResult">
        <include refid="selectHwAboutUsInfoDetailVo"/>
        where us_info_detail_id = #{usInfoDetailId}
    </select>
        
    <insert id="insertHwAboutUsInfoDetail" parameterType="HwAboutUsInfoDetail" useGeneratedKeys="true" keyProperty="usInfoDetailId">
        insert into hw_about_us_info_detail
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="aboutUsInfoId != null">about_us_info_id,</if>
            <if test="usInfoDetailTitle != null">us_info_detail_title,</if>
            <if test="usInfoDetailDesc != null">us_info_detail_desc,</if>
            <if test="usInfoDetailOrder != null">us_info_detail_order,</if>
            <if test="usInfoDetailPic != null">us_info_detail_pic,</if>
            <if test="createTime != null">create_time,</if>
            <if test="createBy != null">create_by,</if>
            <if test="updateTime != null">update_time,</if>
            <if test="updateBy != null">update_by,</if>
         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="aboutUsInfoId != null">#{aboutUsInfoId},</if>
            <if test="usInfoDetailTitle != null">#{usInfoDetailTitle},</if>
            <if test="usInfoDetailDesc != null">#{usInfoDetailDesc},</if>
            <if test="usInfoDetailOrder != null">#{usInfoDetailOrder},</if>
            <if test="usInfoDetailPic != null">#{usInfoDetailPic},</if>
            <if test="createTime != null">#{createTime},</if>
            <if test="createBy != null">#{createBy},</if>
            <if test="updateTime != null">#{updateTime},</if>
            <if test="updateBy != null">#{updateBy},</if>
         </trim>
    </insert>

    <update id="updateHwAboutUsInfoDetail" parameterType="HwAboutUsInfoDetail">
        update hw_about_us_info_detail
        <trim prefix="SET" suffixOverrides=",">
            <if test="aboutUsInfoId != null">about_us_info_id = #{aboutUsInfoId},</if>
            <if test="usInfoDetailTitle != null">us_info_detail_title = #{usInfoDetailTitle},</if>
            <if test="usInfoDetailDesc != null">us_info_detail_desc = #{usInfoDetailDesc},</if>
            <if test="usInfoDetailOrder != null">us_info_detail_order = #{usInfoDetailOrder},</if>
            <if test="usInfoDetailPic != null">us_info_detail_pic = #{usInfoDetailPic},</if>
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="createBy != null">create_by = #{createBy},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="updateBy != null">update_by = #{updateBy},</if>
        </trim>
        where us_info_detail_id = #{usInfoDetailId}
    </update>

    <delete id="deleteHwAboutUsInfoDetailByUsInfoDetailId" parameterType="Long">
        delete from hw_about_us_info_detail where us_info_detail_id = #{usInfoDetailId}
    </delete>

    <delete id="deleteHwAboutUsInfoDetailByUsInfoDetailIds" parameterType="String">
        delete from hw_about_us_info_detail where us_info_detail_id in 
        <foreach item="usInfoDetailId" collection="array" open="(" separator="," close=")">
            #{usInfoDetailId}
        </foreach>
    </delete>
</mapper>

ruoyi-portal/src/main/resources/mapper/portal/HwAboutUsInfoMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.portal.mapper.HwAboutUsInfoMapper">
    
    <resultMap type="HwAboutUsInfo" id="HwAboutUsInfoResult">
        <result property="aboutUsInfoId"    column="about_us_info_id"    />
        <result property="aboutUsInfoType"    column="about_us_info_type"    />
        <result property="aboutUsInfoEtitle"    column="about_us_info_etitle"    />
        <result property="aboutUsInfoTitle"    column="about_us_info_title"    />
        <result property="aboutUsInfoDesc"    column="about_us_info_desc"    />
        <result property="aboutUsInfoOrder"    column="about_us_info_order"    />
        <result property="displayModal"    column="display_modal"    />
        <result property="aboutUsInfoPic"    column="about_us_info_pic"    />
        <result property="createTime"    column="create_time"    />
        <result property="createBy"    column="create_by"    />
        <result property="updateTime"    column="update_time"    />
        <result property="updateBy"    column="update_by"    />
    </resultMap>

    <sql id="selectHwAboutUsInfoVo">
        select about_us_info_id, about_us_info_type, about_us_info_title, about_us_info_etitle,about_us_info_desc, about_us_info_order,display_modal, about_us_info_pic, create_time, create_by, update_time, update_by from hw_about_us_info
    </sql>

    <select id="selectHwAboutUsInfoList" parameterType="HwAboutUsInfo" resultMap="HwAboutUsInfoResult">
        <include refid="selectHwAboutUsInfoVo"/>
        <where>  
            <if test="aboutUsInfoType != null  and aboutUsInfoType != ''"> and about_us_info_type = #{aboutUsInfoType}</if>
            <if test="aboutUsInfoTitle != null  and aboutUsInfoTitle != ''"> and about_us_info_title like concat('%', #{aboutUsInfoTitle }, '%') </if>
            <if test="aboutUsInfoDesc != null  and aboutUsInfoDesc != ''"> and about_us_info_desc like concat('%', #{aboutUsInfoDesc}, '%')</if>
            <if test="aboutUsInfoOrder != null "> and about_us_info_order = #{aboutUsInfoOrder}</if>
            <if test="aboutUsInfoPic != null  and aboutUsInfoPic != ''"> and about_us_info_pic = #{aboutUsInfoPic}</if>
        </where>
    </select>
    
    <select id="selectHwAboutUsInfoByAboutUsInfoId" parameterType="Long" resultMap="HwAboutUsInfoResult">
        <include refid="selectHwAboutUsInfoVo"/>
        where about_us_info_id = #{aboutUsInfoId}
    </select>
        
    <insert id="insertHwAboutUsInfo" parameterType="HwAboutUsInfo" useGeneratedKeys="true" keyProperty="aboutUsInfoId">
        insert into hw_about_us_info
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="aboutUsInfoType != null">about_us_info_type,</if>
            <if test="aboutUsInfoEtitle != null and aboutUsInfoEtitle != ''">about_us_info_etitle,</if>
            <if test="aboutUsInfoTitle != null and aboutUsInfoTitle != ''">about_us_info_title,</if>
            <if test="aboutUsInfoDesc != null and aboutUsInfoDesc != ''">about_us_info_desc,</if>
            <if test="aboutUsInfoOrder != null">about_us_info_order,</if>
            <if test="displayModal != null and displayModal != ''">display_modal,</if>
            <if test="aboutUsInfoPic != null">about_us_info_pic,</if>
            <if test="createTime != null">create_time,</if>
            <if test="createBy != null">create_by,</if>
            <if test="updateTime != null">update_time,</if>
            <if test="updateBy != null">update_by,</if>
         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="aboutUsInfoType != null">#{aboutUsInfoType},</if>
            <if test="aboutUsInfoEtitle != null and aboutUsInfoEtitle != ''">#{aboutUsInfoEtitle},</if>
            <if test="aboutUsInfoTitle != null and aboutUsInfoTitle != ''">#{aboutUsInfoTitle},</if>
            <if test="aboutUsInfoDesc != null and aboutUsInfoDesc != ''">#{aboutUsInfoDesc},</if>
            <if test="aboutUsInfoOrder != null">#{aboutUsInfoOrder},</if>
            <if test="displayModal != null and displayModal != ''">#{displayModal},</if>
            <if test="aboutUsInfoPic != null">#{aboutUsInfoPic},</if>
            <if test="createTime != null">#{createTime},</if>
            <if test="createBy != null">#{createBy},</if>
            <if test="updateTime != null">#{updateTime},</if>
            <if test="updateBy != null">#{updateBy},</if>
         </trim>
    </insert>

    <update id="updateHwAboutUsInfo" parameterType="HwAboutUsInfo">
        update hw_about_us_info
        <trim prefix="SET" suffixOverrides=",">
            <if test="aboutUsInfoType != null">about_us_info_type = #{aboutUsInfoType},</if>
            <if test="aboutUsInfoEtitle != null and aboutUsInfoEtitle != ''">about_us_info_etitle = #{aboutUsInfoEtitle},</if>
            <if test="aboutUsInfoTitle != null and aboutUsInfoTitle != ''">about_us_info_title = #{aboutUsInfoTitle},</if>
            <if test="aboutUsInfoDesc != null and aboutUsInfoDesc != ''">about_us_info_desc = #{aboutUsInfoDesc},</if>
            <if test="aboutUsInfoOrder != null">about_us_info_order = #{aboutUsInfoOrder},</if>
            <if test="displayModal != null and displayModal != ''">display_modal = #{displayModal},</if>
            <if test="aboutUsInfoPic != null">about_us_info_pic = #{aboutUsInfoPic},</if>
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="createBy != null">create_by = #{createBy},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="updateBy != null">update_by = #{updateBy},</if>
        </trim>
        where about_us_info_id = #{aboutUsInfoId}
    </update>

    <delete id="deleteHwAboutUsInfoByAboutUsInfoId" parameterType="Long">
        delete from hw_about_us_info where about_us_info_id = #{aboutUsInfoId}
    </delete>

    <delete id="deleteHwAboutUsInfoByAboutUsInfoIds" parameterType="String">
        delete from hw_about_us_info where about_us_info_id in 
        <foreach item="aboutUsInfoId" collection="array" open="(" separator="," close=")">
            #{aboutUsInfoId}
        </foreach>
    </delete>
</mapper>

ruoyi-portal/src/main/resources/mapper/portal/HwAnalyticsMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.portal.mapper.HwAnalyticsMapper">

    <resultMap id="HwWebVisitDailyResult" type="com.ruoyi.portal.domain.HwWebVisitDaily">
        <result property="statDate" column="stat_date"/>
        <result property="pv" column="pv"/>
        <result property="uv" column="uv"/>
        <result property="ipUv" column="ip_uv"/>
        <result property="avgStayMs" column="avg_stay_ms"/>
        <result property="bounceRate" column="bounce_rate"/>
        <result property="searchCount" column="search_count"/>
        <result property="downloadCount" column="download_count"/>
        <result property="createdAt" column="created_at"/>
        <result property="updatedAt" column="updated_at"/>
    </resultMap>

    <insert id="insertVisitEvent" parameterType="com.ruoyi.portal.domain.HwWebVisitEvent" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO hw_web_visit_event (
            event_type, visitor_id, session_id, path, referrer, utm_source, utm_medium, utm_campaign,
            keyword, ip_hash, ua, device, browser, os, stay_ms, event_time, created_at
        ) VALUES (
            #{eventType}, #{visitorId}, #{sessionId}, #{path}, #{referrer}, #{utmSource}, #{utmMedium}, #{utmCampaign},
            #{keyword}, #{ipHash}, #{ua}, #{device}, #{browser}, #{os}, #{stayMs}, #{eventTime}, NOW()
        )
    </insert>

    <select id="countEventByType" resultType="java.lang.Long">
        SELECT COUNT(1)
        FROM hw_web_visit_event
        WHERE DATE(event_time) = #{statDate}
          AND event_type = #{eventType}
    </select>

    <select id="countDistinctVisitor" resultType="java.lang.Long">
        SELECT COUNT(DISTINCT visitor_id)
        FROM hw_web_visit_event
        WHERE DATE(event_time) = #{statDate}
          AND event_type = 'page_view'
          AND visitor_id IS NOT NULL
          AND visitor_id != ''
    </select>

    <select id="countDistinctIp" resultType="java.lang.Long">
        SELECT COUNT(DISTINCT ip_hash)
        FROM hw_web_visit_event
        WHERE DATE(event_time) = #{statDate}
          AND event_type = 'page_view'
          AND ip_hash IS NOT NULL
          AND ip_hash != ''
    </select>

    <select id="avgStayMs" resultType="java.lang.Long">
        SELECT COALESCE(ROUND(AVG(stay_ms)), 0)
        FROM hw_web_visit_event
        WHERE DATE(event_time) = #{statDate}
          AND event_type = 'page_leave'
          AND stay_ms IS NOT NULL
          AND stay_ms >= 0
    </select>

    <select id="countDistinctSessions" resultType="java.lang.Long">
        SELECT COUNT(DISTINCT session_id)
        FROM hw_web_visit_event
        WHERE DATE(event_time) = #{statDate}
          AND event_type = 'page_view'
          AND session_id IS NOT NULL
          AND session_id != ''
    </select>

    <select id="countSinglePageSessions" resultType="java.lang.Long">
        SELECT COUNT(1)
        FROM (
            SELECT session_id
            FROM hw_web_visit_event
            WHERE DATE(event_time) = #{statDate}
              AND event_type = 'page_view'
              AND session_id IS NOT NULL
              AND session_id != ''
            GROUP BY session_id
            HAVING COUNT(1) = 1
        ) t
    </select>

    <select id="selectTopEntryPages" resultType="com.ruoyi.portal.domain.dto.AnalyticsRankItemDTO">
        SELECT IFNULL(e.path, '/') AS name, COUNT(1) AS value
        FROM hw_web_visit_event e
                 INNER JOIN (
            SELECT session_id, MIN(event_time) AS min_event_time
            FROM hw_web_visit_event
            WHERE DATE(event_time) = #{statDate}
              AND event_type = 'page_view'
              AND session_id IS NOT NULL
              AND session_id != ''
            GROUP BY session_id
        ) s ON s.session_id = e.session_id AND s.min_event_time = e.event_time
        WHERE DATE(e.event_time) = #{statDate}
          AND e.event_type = 'page_view'
        GROUP BY e.path
        ORDER BY value DESC
        LIMIT #{limit}
    </select>

    <select id="selectTopHotPages" resultType="com.ruoyi.portal.domain.dto.AnalyticsRankItemDTO">
        SELECT IFNULL(path, '/') AS name, COUNT(1) AS value
        FROM hw_web_visit_event
        WHERE DATE(event_time) = #{statDate}
          AND event_type = 'page_view'
        GROUP BY path
        ORDER BY value DESC
        LIMIT #{limit}
    </select>

    <select id="selectTopKeywords" resultType="com.ruoyi.portal.domain.dto.AnalyticsRankItemDTO">
        SELECT keyword AS name, COUNT(1) AS value
        FROM hw_web_visit_event
        WHERE DATE(event_time) = #{statDate}
          AND event_type = 'search_submit'
          AND keyword IS NOT NULL
          AND keyword != ''
        GROUP BY keyword
        ORDER BY value DESC
        LIMIT #{limit}
    </select>

    <insert id="upsertDaily" parameterType="com.ruoyi.portal.domain.HwWebVisitDaily">
        INSERT INTO hw_web_visit_daily (
            stat_date, pv, uv, ip_uv, avg_stay_ms, bounce_rate, search_count, download_count, created_at, updated_at
        ) VALUES (
            #{statDate}, #{pv}, #{uv}, #{ipUv}, #{avgStayMs}, #{bounceRate}, #{searchCount}, #{downloadCount}, NOW(), NOW()
        )
        ON DUPLICATE KEY UPDATE
            pv = VALUES(pv),
            uv = VALUES(uv),
            ip_uv = VALUES(ip_uv),
            avg_stay_ms = VALUES(avg_stay_ms),
            bounce_rate = VALUES(bounce_rate),
            search_count = VALUES(search_count),
            download_count = VALUES(download_count),
            updated_at = NOW()
    </insert>

    <select id="selectDailyByDate" resultMap="HwWebVisitDailyResult">
        SELECT stat_date, pv, uv, ip_uv, avg_stay_ms, bounce_rate, search_count, download_count, created_at, updated_at
        FROM hw_web_visit_daily
        WHERE stat_date = #{statDate}
    </select>
</mapper>

ruoyi-portal/src/main/resources/mapper/portal/HwContactUsInfoMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.portal.mapper.HwContactUsInfoMapper">
    
    <resultMap type="HwContactUsInfo" id="HwContactUsInfoResult">
        <result property="contactUsInfoId"    column="contact_us_info_id"    />
        <result property="userName"    column="user_name"    />
        <result property="userEmail"    column="user_email"    />
        <result property="userPhone"    column="user_phone"    />
        <result property="userIp"    column="user_ip"    />
        <result property="remark"    column="remark"    />
        <result property="createTime"    column="create_time"    />
        <result property="createBy"    column="create_by"    />
        <result property="updateTime"    column="update_time"    />
        <result property="updateBy"    column="update_by"    />
    </resultMap>

    <sql id="selectHwContactUsInfoVo">
        select contact_us_info_id, user_name, user_email, user_phone, user_ip, remark,create_time, create_by, update_time, update_by from hw_contact_us_info
    </sql>

    <select id="selectHwContactUsInfoList" parameterType="HwContactUsInfo" resultMap="HwContactUsInfoResult">
        <include refid="selectHwContactUsInfoVo"/>
        <where>  
            <if test="userName != null  and userName != ''"> and user_name like concat('%', #{userName}, '%')</if>
            <if test="userEmail != null  and userEmail != ''"> and user_email like concat('%', #{userEmail}, '%')</if>
            <if test="userPhone != null  and userPhone != ''"> and user_phone like concat('%', #{userPhone}, '%')</if>
            <if test="userIp != null  and userIp != ''"> and user_ip like concat('%', #{userIp}, '%')</if>
        </where>
    </select>
    
    <select id="selectHwContactUsInfoByContactUsInfoId" parameterType="Long" resultMap="HwContactUsInfoResult">
        <include refid="selectHwContactUsInfoVo"/>
        where contact_us_info_id = #{contactUsInfoId}
    </select>
        
    <insert id="insertHwContactUsInfo" parameterType="HwContactUsInfo" useGeneratedKeys="true" keyProperty="contactUsInfoId">
        insert into hw_contact_us_info
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="userName != null and userName != ''">user_name,</if>
            <if test="userEmail != null">user_email,</if>
            <if test="userPhone != null">user_phone,</if>
            <if test="userIp != null">user_ip,</if>
            <if test="remark != null">remark,</if>
            <if test="createTime != null">create_time,</if>
            <if test="createBy != null">create_by,</if>
            <if test="updateTime != null">update_time,</if>
            <if test="updateBy != null">update_by,</if>
         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="userName != null and userName != ''">#{userName},</if>
            <if test="userEmail != null">#{userEmail},</if>
            <if test="userPhone != null">#{userPhone},</if>
            <if test="userIp != null">#{userIp},</if>
            <if test="remark != null">#{remark},</if>
            <if test="createTime != null">#{createTime},</if>
            <if test="createBy != null">#{createBy},</if>
            <if test="updateTime != null">#{updateTime},</if>
            <if test="updateBy != null">#{updateBy},</if>
         </trim>
    </insert>

    <update id="updateHwContactUsInfo" parameterType="HwContactUsInfo">
        update hw_contact_us_info
        <trim prefix="SET" suffixOverrides=",">
            <if test="userName != null and userName != ''">user_name = #{userName},</if>
            <if test="userEmail != null">user_email = #{userEmail},</if>
            <if test="userPhone != null">user_phone = #{userPhone},</if>
            <if test="userIp != null">user_ip = #{userIp},</if>
            <if test="remark != null">remark = #{remark},</if>
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="createBy != null">create_by = #{createBy},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="updateBy != null">update_by = #{updateBy},</if>
        </trim>
        where contact_us_info_id = #{contactUsInfoId}
    </update>

    <delete id="deleteHwContactUsInfoByContactUsInfoId" parameterType="Long">
        delete from hw_contact_us_info where contact_us_info_id = #{contactUsInfoId}
    </delete>

    <delete id="deleteHwContactUsInfoByContactUsInfoIds" parameterType="String">
        delete from hw_contact_us_info where contact_us_info_id in 
        <foreach item="contactUsInfoId" collection="array" open="(" separator="," close=")">
            #{contactUsInfoId}
        </foreach>
    </delete>
</mapper>

ruoyi-portal/src/main/resources/mapper/portal/HwPortalConfigMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.portal.mapper.HwPortalConfigMapper">
    
    <resultMap type="HwPortalConfig" id="HwPortalConfigResult">
        <result property="portalConfigId"    column="portal_config_id"    />
        <result property="portalConfigType"    column="portal_config_type"    />
        <result property="portalConfigTypeId"    column="portal_config_type_id"    />
        <result property="portalConfigTitle"    column="portal_config_title"    />
        <result property="portalConfigOrder"    column="portal_config_order"    />
        <result property="portalConfigDesc"    column="portal_config_desc"    />
        <result property="buttonName"    column="button_name"    />
        <result property="routerAddress"    column="router_address"    />
        <result property="portalConfigPic"    column="portal_config_pic"    />
        <result property="createTime"    column="create_time"    />
        <result property="createBy"    column="create_by"    />
        <result property="updateTime"    column="update_time"    />
        <result property="updateBy"    column="update_by"    />
        <result property="configTypeName"    column="config_type_name"    />
    </resultMap>

    <resultMap type="HwPortalConfig" id="HwPortalConfigResult2">
        <result property="portalConfigId"    column="portal_config_id"    />
        <result property="portalConfigType"    column="portal_config_type"    />
        <result property="portalConfigTypeId"    column="portal_config_type_id"    />
        <result property="portalConfigTitle"    column="portal_config_title"    />
        <result property="portalConfigOrder"    column="portal_config_order"    />
        <result property="portalConfigDesc"    column="portal_config_desc"    />
        <result property="buttonName"    column="button_name"    />
        <result property="routerAddress"    column="router_address"    />
        <result property="portalConfigPic"    column="portal_config_pic"    />
        <result property="createTime"    column="create_time"    />
        <result property="createBy"    column="create_by"    />
        <result property="updateTime"    column="update_time"    />
        <result property="updateBy"    column="update_by"    />
        <result property="configTypeName"    column="config_type_name"    />

        <result property="homeConfigTypePic"    column="home_config_type_pic"    />
        <result property="homeConfigTypeIcon"    column="home_config_type_icon"    />
        <result property="homeConfigTypeName"    column="home_config_type_name"    />
        <result property="homeConfigTypeClassfication"    column="config_type_classfication"    />
        <result property="parentId"    column="parent_id"    />
        <result property="ancestors"    column="ancestors"    />
    </resultMap>

    <sql id="selectHwPortalConfigVo">
        select portal_config_id, portal_config_type,portal_config_type_id,  portal_config_title, portal_config_order,
               portal_config_desc, button_name, router_address, portal_config_pic, create_time, create_by, update_time,
               update_by
        from hw_portal_config
    </sql>

    <sql id="selectHwPortalConfigVo2">
        select hpc.portal_config_id, hpc.portal_config_type,hpc.portal_config_type_id,  hpc.portal_config_title, hpc.portal_config_order,
               hpc.portal_config_desc, hpc.button_name, hpc.router_address, hpc.portal_config_pic, hpc.create_time, hpc.create_by, hpc.update_time,
               hpc.update_by,
               hpct.config_type_name,
               hpct.home_config_type_pic,
               hpct.config_type_icon,
               hpct.home_config_type_name,
               hpct.config_type_classfication,
               hpct.parent_id,
               hpct.ancestors
        from hw_portal_config hpc
                 left join hw_portal_config_type hpct on hpc.portal_config_type_id = hpct.config_type_id
    </sql>

    <select id="selectHwPortalConfigList" parameterType="HwPortalConfig" resultMap="HwPortalConfigResult">
        <include refid="selectHwPortalConfigVo"/>
        <where>  
            <if test="portalConfigType != null  and portalConfigType != ''"> and portal_config_type = #{portalConfigType}</if>
            <if test="portalConfigTypeId != null "> and portal_config_type_id = #{portalConfigTypeId}</if>
            <if test="portalConfigTitle != null  and portalConfigTitle != ''"> and portal_config_title like concat('%', #{portalConfigTitle}, '%')</if>
            <if test="portalConfigOrder != null "> and portal_config_order = #{portalConfigOrder}</if>
            <if test="portalConfigDesc != null  and portalConfigDesc != ''"> and portal_config_desc = #{portalConfigDesc}</if>
            <if test="buttonName != null  and buttonName != ''"> and button_name like concat('%', #{buttonName}, '%')</if>
            <if test="routerAddress != null  and routerAddress != ''"> and router_address = #{routerAddress}</if>
            <if test="portalConfigPic != null  and portalConfigPic != ''"> and portal_config_pic = #{portalConfigPic}</if>
        </where>
    </select>

    <select id="selectHwPortalConfigList2" parameterType="HwPortalConfig" resultMap="HwPortalConfigResult2">
        <include refid="selectHwPortalConfigVo2"/>
        <where>
            <if test="portalConfigType != null  and portalConfigType != ''"> and portal_config_type = #{portalConfigType}</if>
            <if test="portalConfigTypeId != null "> and portal_config_type_id = #{portalConfigTypeId}</if>
            <if test="portalConfigTitle != null  and portalConfigTitle != ''"> and portal_config_title like concat('%', #{portalConfigTitle}, '%')</if>
            <if test="portalConfigOrder != null "> and portal_config_order = #{portalConfigOrder}</if>
            <if test="portalConfigDesc != null  and portalConfigDesc != ''"> and portal_config_desc = #{portalConfigDesc}</if>
            <if test="buttonName != null  and buttonName != ''"> and button_name like concat('%', #{buttonName}, '%')</if>
            <if test="routerAddress != null  and routerAddress != ''"> and router_address = #{routerAddress}</if>
            <if test="portalConfigPic != null  and portalConfigPic != ''"> and portal_config_pic = #{portalConfigPic}</if>
        </where>
    </select>
    
    <select id="selectHwPortalConfigByPortalConfigId" parameterType="Long" resultMap="HwPortalConfigResult">
        <include refid="selectHwPortalConfigVo"/>
        where portal_config_id = #{portalConfigId}
    </select>
        
    <insert id="insertHwPortalConfig" parameterType="HwPortalConfig" useGeneratedKeys="true" keyProperty="portalConfigId">
        insert into hw_portal_config
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="portalConfigType != null and portalConfigType != ''">portal_config_type,</if>
            <if test="portalConfigTypeId != null">portal_config_type_id,</if>
            <if test="portalConfigTitle != null and portalConfigTitle != ''">portal_config_title,</if>
            <if test="portalConfigOrder != null">portal_config_order,</if>
            <if test="portalConfigDesc != null">portal_config_desc,</if>
            <if test="buttonName != null">button_name,</if>
            <if test="routerAddress != null">router_address,</if>
            <if test="portalConfigPic != null and portalConfigPic != ''">portal_config_pic,</if>
            <if test="createTime != null">create_time,</if>
            <if test="createBy != null">create_by,</if>
            <if test="updateTime != null">update_time,</if>
            <if test="updateBy != null">update_by,</if>
         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="portalConfigType != null and portalConfigType != ''">#{portalConfigType},</if>
            <if test="portalConfigTypeId != null">#{portalConfigTypeId},</if>
            <if test="portalConfigTitle != null and portalConfigTitle != ''">#{portalConfigTitle},</if>
            <if test="portalConfigOrder != null">#{portalConfigOrder},</if>
            <if test="portalConfigDesc != null">#{portalConfigDesc},</if>
            <if test="buttonName != null">#{buttonName},</if>
            <if test="routerAddress != null">#{routerAddress},</if>
            <if test="portalConfigPic != null and portalConfigPic != ''">#{portalConfigPic},</if>
            <if test="createTime != null">#{createTime},</if>
            <if test="createBy != null">#{createBy},</if>
            <if test="updateTime != null">#{updateTime},</if>
            <if test="updateBy != null">#{updateBy},</if>
         </trim>
    </insert>

    <update id="updateHwPortalConfig" parameterType="HwPortalConfig">
        update hw_portal_config
        <trim prefix="SET" suffixOverrides=",">
            <if test="portalConfigType != null and portalConfigType != ''">portal_config_type = #{portalConfigType},</if>
            <if test="portalConfigTypeId != null">portal_config_type_id = #{portalConfigTypeId},</if>
            <if test="portalConfigTitle != null and portalConfigTitle != ''">portal_config_title = #{portalConfigTitle},</if>
            <if test="portalConfigOrder != null">portal_config_order = #{portalConfigOrder},</if>
            <if test="portalConfigDesc != null">portal_config_desc = #{portalConfigDesc},</if>
            <if test="buttonName != null">button_name = #{buttonName},</if>
            <if test="routerAddress != null">router_address = #{routerAddress},</if>
            <if test="portalConfigPic != null and portalConfigPic != ''">portal_config_pic = #{portalConfigPic},</if>
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="createBy != null">create_by = #{createBy},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="updateBy != null">update_by = #{updateBy},</if>
        </trim>
        where portal_config_id = #{portalConfigId}
    </update>

    <delete id="deleteHwPortalConfigByPortalConfigId" parameterType="Long">
        delete from hw_portal_config where portal_config_id = #{portalConfigId}
    </delete>

    <delete id="deleteHwPortalConfigByPortalConfigIds" parameterType="String">
        delete from hw_portal_config where portal_config_id in 
        <foreach item="portalConfigId" collection="array" open="(" separator="," close=")">
            #{portalConfigId}
        </foreach>
    </delete>



    <sql id="selectHwPortalConfigJoinVo">
        select hpc.portal_config_id, hpc.portal_config_type,hpc.portal_config_type_id,
               hpc.portal_config_title, hpc.portal_config_order, hpc.portal_config_desc,
               hpc.button_name, hpc.router_address, hpc.portal_config_pic,
               hpc.create_time, hpc.create_by, hpc.update_time, hpc.update_by,hpct.config_type_name from hw_portal_config hpc
                   left join hw_portal_config_type hpct on hpc.portal_config_type_id =  hpct.config_type_id
    </sql>

    <select id="selectHwPortalConfigJoinList" parameterType="HwPortalConfig" resultMap="HwPortalConfigResult">
        <include refid="selectHwPortalConfigJoinVo"/>
        <where>
            <if test="portalConfigType != null  and portalConfigType != ''"> and hpc.portal_config_type = #{portalConfigType}</if>
            <if test="portalConfigTypeId != null "> and hpc.portal_config_type_id = #{portalConfigTypeId}</if>
            <if test="portalConfigTitle != null  and portalConfigTitle != ''"> and hpc.portal_config_title like concat('%', #{portalConfigTitle}, '%')</if>
            <if test="portalConfigOrder != null "> and hpc.portal_config_order = #{portalConfigOrder}</if>
            <if test="portalConfigDesc != null  and portalConfigDesc != ''"> and hpc.portal_config_desc = #{portalConfigDesc}</if>
            <if test="buttonName != null  and buttonName != ''"> and hpc.button_name like concat('%', #{buttonName}, '%')</if>
            <if test="routerAddress != null  and routerAddress != ''"> and hpc.router_address = #{routerAddress}</if>
            <if test="portalConfigPic != null  and portalConfigPic != ''"> and hpc.portal_config_pic = #{portalConfigPic}</if>
        </where>
    </select>

</mapper>

ruoyi-portal/src/main/resources/mapper/portal/HwPortalConfigTypeMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.portal.mapper.HwPortalConfigTypeMapper">
    
    <resultMap type="HwPortalConfigType" id="HwPortalConfigTypeResult">
        <result property="configTypeId"    column="config_type_id"    />
        <result property="configTypeClassfication"    column="config_type_classfication"    />
        <result property="configTypeName"    column="config_type_name"    />
        <result property="homeConfigTypeName"    column="home_config_type_name"    />
        <result property="configTypeDesc"    column="config_type_desc"    />
        <result property="configTypeIcon"    column="config_type_icon"    />
        <result property="homeConfigTypePic"    column="home_config_type_pic"    />
        <result property="parentId"    column="parent_id"    />
        <result property="ancestors"    column="ancestors"    />
        <result property="createTime"    column="create_time"    />
        <result property="createBy"    column="create_by"    />
        <result property="updateTime"    column="update_time"    />
        <result property="updateBy"    column="update_by"    />
    </resultMap>

    <sql id="selectHwPortalConfigTypeVo">
        select config_type_id, config_type_classfication, config_type_name, home_config_type_name, config_type_desc, config_type_icon, home_config_type_pic, parent_id, ancestors, create_time, create_by, update_time, update_by
        from hw_portal_config_type
    </sql>

    <select id="selectHwPortalConfigTypeList" parameterType="HwPortalConfigType" resultMap="HwPortalConfigTypeResult">
        <include refid="selectHwPortalConfigTypeVo"/>
        <where>  
            <if test="configTypeClassfication != null  and configTypeClassfication != ''"> and config_type_classfication = #{configTypeClassfication}</if>
            <if test="configTypeName != null  and configTypeName != ''"> and config_type_name like concat('%', #{configTypeName}, '%')</if>
            <if test="homeConfigTypeName != null  and homeConfigTypeName != ''"> and home_config_type_name like concat('%', #{homeConfigTypeName}, '%')</if>
            <if test="configTypeDesc != null  and configTypeDesc != ''"> and config_type_desc = #{configTypeDesc}</if>
            <if test="configTypeIcon != null  and configTypeIcon != ''"> and config_type_icon = #{configTypeIcon}</if>
            <if test="homeConfigTypePic != null  and homeConfigTypePic != ''"> and home_config_type_pic = #{homeConfigTypePic}</if>
            <if test="parentId != null "> and parent_id = #{parentId}</if>
            <if test="ancestors != null  and ancestors != ''"> and ancestors = #{ancestors}</if>
        </where>
    </select>
    
    <select id="selectHwPortalConfigTypeByConfigTypeId" parameterType="Long" resultMap="HwPortalConfigTypeResult">
        <include refid="selectHwPortalConfigTypeVo"/>
        where config_type_id = #{configTypeId}
    </select>
        
    <insert id="insertHwPortalConfigType" parameterType="HwPortalConfigType" useGeneratedKeys="true" keyProperty="configTypeId">
        insert into hw_portal_config_type
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="configTypeClassfication != null and configTypeClassfication != ''">config_type_classfication,</if>
            <if test="configTypeName != null and configTypeName != ''">config_type_name,</if>
            <if test="homeConfigTypeName != null">home_config_type_name,</if>
            <if test="configTypeDesc != null">config_type_desc,</if>
            <if test="configTypeIcon != null">config_type_icon,</if>
            <if test="homeConfigTypePic != null">home_config_type_pic,</if>
            <if test="parentId != null">parent_id,</if>
            <if test="ancestors != null">ancestors,</if>
            <if test="createTime != null">create_time,</if>
            <if test="createBy != null">create_by,</if>
            <if test="updateTime != null">update_time,</if>
            <if test="updateBy != null">update_by,</if>
         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="configTypeClassfication != null and configTypeClassfication != ''">#{configTypeClassfication},</if>
            <if test="configTypeName != null and configTypeName != ''">#{configTypeName},</if>
            <if test="homeConfigTypeName != null">#{homeConfigTypeName},</if>
            <if test="configTypeDesc != null">#{configTypeDesc},</if>
            <if test="configTypeIcon != null">#{configTypeIcon},</if>
            <if test="homeConfigTypePic != null">#{homeConfigTypePic},</if>
            <if test="parentId != null">#{parentId},</if>
            <if test="ancestors != null">#{ancestors},</if>
            <if test="createTime != null">#{createTime},</if>
            <if test="createBy != null">#{createBy},</if>
            <if test="updateTime != null">#{updateTime},</if>
            <if test="updateBy != null">#{updateBy},</if>
         </trim>
    </insert>

    <update id="updateHwPortalConfigType" parameterType="HwPortalConfigType">
        update hw_portal_config_type
        <trim prefix="SET" suffixOverrides=",">
            <if test="configTypeClassfication != null and configTypeClassfication != ''">config_type_classfication = #{configTypeClassfication},</if>
            <if test="configTypeName != null and configTypeName != ''">config_type_name = #{configTypeName},</if>
            <if test="homeConfigTypeName != null">home_config_type_name = #{homeConfigTypeName},</if>
            <if test="configTypeDesc != null">config_type_desc = #{configTypeDesc},</if>
            <if test="configTypeIcon != null">config_type_icon = #{configTypeIcon},</if>
            <if test="homeConfigTypePic != null">home_config_type_pic = #{homeConfigTypePic},</if>
            <if test="parentId != null">parent_id = #{parentId},</if>
            <if test="ancestors != null">ancestors = #{ancestors},</if>
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="createBy != null">create_by = #{createBy},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="updateBy != null">update_by = #{updateBy},</if>
        </trim>
        where config_type_id = #{configTypeId}
    </update>

    <delete id="deleteHwPortalConfigTypeByConfigTypeId" parameterType="Long">
        delete from hw_portal_config_type where config_type_id = #{configTypeId}
    </delete>

    <delete id="deleteHwPortalConfigTypeByConfigTypeIds" parameterType="String">
        delete from hw_portal_config_type where config_type_id in 
        <foreach item="configTypeId" collection="array" open="(" separator="," close=")">
            #{configTypeId}
        </foreach>
    </delete>
</mapper>

ruoyi-portal/src/main/resources/mapper/portal/HwProductCaseInfoMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.portal.mapper.HwProductCaseInfoMapper">
    
    <resultMap type="HwProductCaseInfo" id="HwProductCaseInfoResult">
        <result property="caseInfoId"    column="case_info_id"    />
        <result property="caseInfoTitle"    column="case_info_title"    />
        <result property="configTypeId"    column="config_type_id"    />
        <result property="typicalFlag"    column="typical_flag"    />
        <result property="caseInfoDesc"    column="case_info_desc"    />
        <result property="caseInfoPic"    column="case_info_pic"    />
        <result property="caseInfoHtml"    column="case_info_html"    />
        <result property="createTime"    column="create_time"    />
        <result property="createBy"    column="create_by"    />
        <result property="updateTime"    column="update_time"    />
        <result property="updateBy"    column="update_by"    />
    </resultMap>

    <sql id="selectHwProductCaseInfoWithHtmlVo">
        select case_info_id, case_info_title, config_type_id, typical_flag, case_info_desc, case_info_pic, case_info_html, create_time, create_by, update_time, update_by from hw_product_case_info hpci
    </sql>

    <sql id="selectHwProductCaseInfoVo">
        select case_info_id, case_info_title, config_type_id, typical_flag, case_info_desc, case_info_pic, create_time, create_by, update_time, update_by from hw_product_case_info hpci
    </sql>


    <select id="selectHwProductCaseInfoList" parameterType="HwProductCaseInfo" resultMap="HwProductCaseInfoResult">
        <include refid="selectHwProductCaseInfoVo"/>
        <where>  
            <if test="caseInfoTitle != null  and caseInfoTitle != ''"> and case_info_title = #{caseInfoTitle}</if>

            <if test="typicalFlag != null  and typicalFlag != ''"> and typical_flag = #{typicalFlag}</if>
            <if test="caseInfoDesc != null  and caseInfoDesc != ''"> and case_info_desc = #{caseInfoDesc}</if>
            <if test="caseInfoPic != null  and caseInfoPic != ''"> and case_info_pic = #{caseInfoPic}</if>
            <if test="caseInfoHtml != null  and caseInfoHtml != ''"> and case_info_html = #{caseInfoHtml}</if>
            <if test="homeTypicalFlag != null  and homeTypicalFlag != '' and configTypeId!=null"> and exists (select 1 from hw_portal_config_type hpct where hpct.parent_id=#{configTypeId} and hpct.config_type_id =hpci.config_type_id)</if>
            <if test='(homeTypicalFlag == null  or homeTypicalFlag == "") and configTypeId != null '> and config_type_id = #{configTypeId}</if>

        </where>
    </select>
    
    <select id="selectHwProductCaseInfoByCaseInfoId" parameterType="Long" resultMap="HwProductCaseInfoResult">
        <include refid="selectHwProductCaseInfoWithHtmlVo"/>
        where case_info_id = #{caseInfoId}
    </select>
        
    <insert id="insertHwProductCaseInfo" parameterType="HwProductCaseInfo" useGeneratedKeys="true" keyProperty="caseInfoId">
        insert into hw_product_case_info
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="caseInfoTitle != null and caseInfoTitle != ''">case_info_title,</if>
            <if test="configTypeId != null">config_type_id,</if>
            <if test="typicalFlag != null and typicalFlag != ''">typical_flag,</if>
            <if test="caseInfoDesc != null and caseInfoDesc != ''">case_info_desc,</if>
            <if test="caseInfoPic != null and caseInfoPic != ''">case_info_pic,</if>
            <if test="caseInfoHtml != null and caseInfoHtml != ''">case_info_html,</if>
            <if test="createTime != null">create_time,</if>
            <if test="createBy != null">create_by,</if>
            <if test="updateTime != null">update_time,</if>
            <if test="updateBy != null">update_by,</if>
         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="caseInfoTitle != null and caseInfoTitle != ''">#{caseInfoTitle},</if>
            <if test="configTypeId != null">#{configTypeId},</if>
            <if test="typicalFlag != null and typicalFlag != ''">#{typicalFlag},</if>
            <if test="caseInfoDesc != null and caseInfoDesc != ''">#{caseInfoDesc},</if>
            <if test="caseInfoPic != null and caseInfoPic != ''">#{caseInfoPic},</if>
            <if test="caseInfoHtml != null and caseInfoHtml != ''">#{caseInfoHtml},</if>
            <if test="createTime != null">#{createTime},</if>
            <if test="createBy != null">#{createBy},</if>
            <if test="updateTime != null">#{updateTime},</if>
            <if test="updateBy != null">#{updateBy},</if>
         </trim>
    </insert>

    <update id="updateHwProductCaseInfo" parameterType="HwProductCaseInfo">
        update hw_product_case_info
        <trim prefix="SET" suffixOverrides=",">
            <if test="caseInfoTitle != null and caseInfoTitle != ''">case_info_title = #{caseInfoTitle},</if>
            <if test="configTypeId != null">config_type_id = #{configTypeId},</if>
            <if test="typicalFlag != null and typicalFlag != ''">typical_flag = #{typicalFlag},</if>
            <if test="caseInfoDesc != null and caseInfoDesc != ''">case_info_desc = #{caseInfoDesc},</if>
            <if test="caseInfoPic != null and caseInfoPic != ''">case_info_pic = #{caseInfoPic},</if>
            <if test="caseInfoHtml != null and caseInfoHtml != ''">case_info_html = #{caseInfoHtml},</if>
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="createBy != null">create_by = #{createBy},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="updateBy != null">update_by = #{updateBy},</if>
        </trim>
        where case_info_id = #{caseInfoId}
    </update>

    <delete id="deleteHwProductCaseInfoByCaseInfoId" parameterType="Long">
        delete from hw_product_case_info where case_info_id = #{caseInfoId}
    </delete>

    <delete id="deleteHwProductCaseInfoByCaseInfoIds" parameterType="String">
        delete from hw_product_case_info where case_info_id in 
        <foreach item="caseInfoId" collection="array" open="(" separator="," close=")">
            #{caseInfoId}
        </foreach>
    </delete>



    <sql id="selectHwProductCaseInfoJoinVo">
        select hpci.case_info_id, hpci.case_info_title, hpci.config_type_id, hpci.typical_flag, hpci.case_info_desc, hpci.case_info_pic, hpci.create_time,
               hpci.create_by, hpci.update_time, hpci.update_by,hpct.config_type_name from hw_product_case_info hpci left join hw_portal_config_type hpct on hpci.config_type_id=hpct.config_type_id
    </sql>


    <select id="selectHwProductCaseInfoJoinList" parameterType="HwProductCaseInfo" resultMap="HwProductCaseInfoResult">
        <include refid="selectHwProductCaseInfoJoinVo"/>
        <where>
            <if test="caseInfoTitle != null  and caseInfoTitle != ''"> and hpci.case_info_title like concat('%', #{caseInfoTitle}, '%')</if>
            <if test="configTypeId != null  and configTypeId != ''"> and hpci.config_type_id = #{configTypeId}</if>
            <if test="typicalFlag != null  and typicalFlag != ''"> and hpci.typical_flag = #{typicalFlag}</if>
            <if test="caseInfoDesc != null  and caseInfoDesc != ''"> and case_info_desc = #{caseInfoDesc}</if>
            <if test="caseInfoPic != null  and caseInfoPic != ''"> and case_info_pic = #{caseInfoPic}</if>
            <if test="caseInfoHtml != null  and caseInfoHtml != ''"> and case_info_html = #{caseInfoHtml}</if>
            <if test="homeTypicalFlag != null  and homeTypicalFlag != '' and configTypeId!=null"> and exists (select 1 from hw_portal_config_type hpct where hpct.parent_id=#{configTypeId} and hpct.config_type_id =hpci.config_type_id)</if>
            <if test='(homeTypicalFlag == null  or homeTypicalFlag == "") and configTypeId != null '> and config_type_id = #{configTypeId}</if>

        </where>
    </select>

</mapper>

ruoyi-portal/src/main/resources/mapper/portal/HwProductInfoDetailMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.portal.mapper.HwProductInfoDetailMapper">
    
    <resultMap type="HwProductInfoDetail" id="HwProductInfoDetailResult">
        <result property="productInfoDetailId"    column="product_info_detail_id"    />
        <result property="parentId"    column="parent_id"    />
        <result property="productInfoId"    column="product_info_id"    />
        <result property="configModal"    column="config_modal"    />
        <result property="productInfoDetailTitle"    column="product_info_detail_title"    />
        <result property="productInfoDetailDesc"    column="product_info_detail_desc"    />
        <result property="productInfoDetailOrder"    column="product_info_detail_order"    />
        <result property="productInfoDetailPic"    column="product_info_detail_pic"    />
        <result property="ancestors"    column="ancestors"    />
        <result property="createTime"    column="create_time"    />
        <result property="createBy"    column="create_by"    />
        <result property="updateTime"    column="update_time"    />
        <result property="updateBy"    column="update_by"    />
    </resultMap>

    <sql id="selectHwProductInfoDetailVo">
        select product_info_detail_id, parent_id, product_info_id, config_modal, product_info_detail_title, product_info_detail_desc, product_info_detail_order, product_info_detail_pic, ancestors, create_time, create_by, update_time, update_by
        from hw_product_info_detail
    </sql>

    <select id="selectHwProductInfoDetailList" parameterType="HwProductInfoDetail" resultMap="HwProductInfoDetailResult">
        <include refid="selectHwProductInfoDetailVo"/>
        <where>  
            <if test="parentId != null  and parentId != ''"> and parent_id = #{parentId}</if>
            <if test="productInfoId != null "> and product_info_id = #{productInfoId}</if>
            <if test="configModal != null  and configModal != ''"> and config_modal = #{configModal}</if>
            <if test="productInfoDetailTitle != null  and productInfoDetailTitle != ''"> and product_info_detail_title like concat('%', #{productInfoDetailTitle}, '%')</if>
            <if test="productInfoDetailDesc != null  and productInfoDetailDesc != ''"> and product_info_detail_desc like concat('%', #{productInfoDetailDesc}, '%')</if>
            <if test="productInfoDetailOrder != null "> and product_info_detail_order = #{productInfoDetailOrder}</if>
            <if test="productInfoDetailPic != null  and productInfoDetailPic != ''"> and product_info_detail_pic = #{productInfoDetailPic}</if>
            <if test="ancestors != null  and ancestors != ''"> and ancestors = #{ancestors}</if>
        </where>
    </select>
    
    <select id="selectHwProductInfoDetailByProductInfoDetailId" parameterType="Long" resultMap="HwProductInfoDetailResult">
        <include refid="selectHwProductInfoDetailVo"/>
        where product_info_detail_id = #{productInfoDetailId}
    </select>
        
    <insert id="insertHwProductInfoDetail" parameterType="HwProductInfoDetail" useGeneratedKeys="true" keyProperty="productInfoDetailId">
        insert into hw_product_info_detail
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="parentId != null">parent_id,</if>
            <if test="productInfoId != null">product_info_id,</if>
            <if test="configModal != null">config_modal,</if>
            <if test="productInfoDetailTitle != null and productInfoDetailTitle != ''">product_info_detail_title,</if>
            <if test="productInfoDetailDesc != null and productInfoDetailDesc != ''">product_info_detail_desc,</if>
            <if test="productInfoDetailOrder != null">product_info_detail_order,</if>
            <if test="productInfoDetailPic != null">product_info_detail_pic,</if>
            <if test="ancestors != null and ancestors != ''">ancestors,</if>
            <if test="createTime != null">create_time,</if>
            <if test="createBy != null">create_by,</if>
            <if test="updateTime != null">update_time,</if>
            <if test="updateBy != null">update_by,</if>
         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="parentId != null">#{parentId},</if>
            <if test="productInfoId != null">#{productInfoId},</if>
            <if test="configModal != null">#{configModal},</if>
            <if test="productInfoDetailTitle != null and productInfoDetailTitle != ''">#{productInfoDetailTitle},</if>
            <if test="productInfoDetailDesc != null and productInfoDetailDesc != ''">#{productInfoDetailDesc},</if>
            <if test="productInfoDetailOrder != null">#{productInfoDetailOrder},</if>
            <if test="productInfoDetailPic != null">#{productInfoDetailPic},</if>
            <if test="ancestors != null and ancestors != ''">#{ancestors},</if>
            <if test="createTime != null">#{createTime},</if>
            <if test="createBy != null">#{createBy},</if>
            <if test="updateTime != null">#{updateTime},</if>
            <if test="updateBy != null">#{updateBy},</if>
         </trim>
    </insert>

    <update id="updateHwProductInfoDetail" parameterType="HwProductInfoDetail">
        update hw_product_info_detail
        <trim prefix="SET" suffixOverrides=",">
            <if test="parentId != null">parent_id = #{parentId},</if>
            <if test="productInfoId != null">product_info_id = #{productInfoId},</if>
            <if test="configModal != null">config_modal = #{configModal},</if>
            <if test="productInfoDetailTitle != null and productInfoDetailTitle != ''">product_info_detail_title = #{productInfoDetailTitle},</if>
            <if test="productInfoDetailDesc != null and productInfoDetailDesc != ''">product_info_detail_desc = #{productInfoDetailDesc},</if>
            <if test="productInfoDetailOrder != null">product_info_detail_order = #{productInfoDetailOrder},</if>
            <if test="productInfoDetailPic != null">product_info_detail_pic = #{productInfoDetailPic},</if>
            <if test="ancestors != null and ancestors != ''">ancestors = #{ancestors},</if>
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="createBy != null">create_by = #{createBy},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="updateBy != null">update_by = #{updateBy},</if>
        </trim>
        where product_info_detail_id = #{productInfoDetailId}
    </update>

    <delete id="deleteHwProductInfoDetailByProductInfoDetailId" parameterType="Long">
        delete from hw_product_info_detail where product_info_detail_id = #{productInfoDetailId}
    </delete>

    <delete id="deleteHwProductInfoDetailByProductInfoDetailIds" parameterType="String">
        delete from hw_product_info_detail where product_info_detail_id in 
        <foreach item="productInfoDetailId" collection="array" open="(" separator="," close=")">
            #{productInfoDetailId}
        </foreach>
    </delete>
</mapper>

ruoyi-portal/src/main/resources/mapper/portal/HwProductInfoMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.portal.mapper.HwProductInfoMapper">
    
    <resultMap type="HwProductInfo" id="HwProductInfoResult">
        <result property="productInfoId"    column="product_info_id"    />
        <result property="configTypeId"    column="config_type_id"    />
        <result property="tabFlag"    column="tab_flag"    />
        <result property="configModal"    column="config_modal"    />
        <result property="productInfoEtitle"    column="product_info_etitle"    />
        <result property="productInfoCtitle"    column="product_info_ctitle"    />
        <result property="productInfoOrder"    column="product_info_order"    />
        <result property="createTime"    column="create_time"    />
        <result property="createBy"    column="create_by"    />
        <result property="updateTime"    column="update_time"    />
        <result property="updateBy"    column="update_by"    />

        <result property="parentId"    column="parent_id"    />
        <result property="configTypeName"    column="config_type_name"    />


    </resultMap>

    <resultMap id="HwProductInfoHwProductInfoDetailResult" type="HwProductInfo" extends="HwProductInfoResult">
        <collection property="hwProductInfoDetailList" notNullColumn="sub_product_info_detail_id" javaType="java.util.List" resultMap="HwProductInfoDetailResult" />
    </resultMap>

    <resultMap type="HwProductInfoDetail" id="HwProductInfoDetailResult">
        <result property="productInfoDetailId"    column="sub_product_info_detail_id"    />
        <result property="parentId"    column="sub_parent_id"    />
        <result property="productInfoId"    column="sub_product_info_id"    />
        <result property="productInfoDetailTitle"    column="sub_product_info_detail_title"    />
        <result property="productInfoDetailDesc"    column="sub_product_info_detail_desc"    />
        <result property="productInfoDetailOrder"    column="sub_product_info_detail_order"    />
        <result property="productInfoDetailPic"    column="sub_product_info_detail_pic"    />
        <result property="ancestors"    column="sub_ancestors"    />
        <result property="createTime"    column="sub_create_time"    />
        <result property="createBy"    column="sub_create_by"    />
        <result property="updateTime"    column="sub_update_time"    />
        <result property="updateBy"    column="sub_update_by"    />
        <result property="configModel"    column="config_model"    />
    </resultMap>

    <sql id="selectHwProductInfoVo">
        select product_info_id, config_type_id, tab_flag, config_modal, product_info_etitle, product_info_ctitle, product_info_order, create_time, create_by, update_time, update_by from hw_product_info
    </sql>

    <select id="selectHwProductInfoList" parameterType="HwProductInfo" resultMap="HwProductInfoResult">
        <include refid="selectHwProductInfoVo"/>
        <where>  
            <if test="configTypeId != null  and configTypeId != ''"> and config_type_id = #{configTypeId}</if>
            <if test="tabFlag != null  and tabFlag != ''"> and tab_flag = #{tabFlag}</if>
            <if test="configModal != null  and configModal != ''"> and config_modal = #{configModal}</if>
            <if test="productInfoEtitle != null "> and product_info_etitle like concat('%', #{productInfoEtitle}, '%')</if>
            <if test="productInfoCtitle != null  and productInfoCtitle != ''"> and product_info_ctitle like concat('%', #{productInfoCtitle}, '%')</if>
            <if test="productInfoOrder != null "> and product_info_order = #{productInfoOrder}</if>
        </where>
    </select>
    
    <select id="selectHwProductInfoByProductInfoId" parameterType="Long" resultMap="HwProductInfoResult">
        <include refid="selectHwProductInfoVo"/>
        where product_info_id = #{productInfoId}
    </select>
        
    <insert id="insertHwProductInfo" parameterType="HwProductInfo" useGeneratedKeys="true" keyProperty="productInfoId">
        insert into hw_product_info
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="configTypeId != null and configTypeId != ''">config_type_id,</if>
            <if test="tabFlag != null and tabFlag != ''">tab_flag,</if>
            <if test="configModal != null and configModal != ''">config_modal,</if>
            <if test="productInfoEtitle != null">product_info_etitle,</if>
            <if test="productInfoCtitle != null and productInfoCtitle != ''">product_info_ctitle,</if>
            <if test="productInfoOrder != null">product_info_order,</if>
            <if test="createTime != null">create_time,</if>
            <if test="createBy != null">create_by,</if>
            <if test="updateTime != null">update_time,</if>
            <if test="updateBy != null">update_by,</if>
         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="configTypeId != null and configTypeId != ''">#{configTypeId},</if>
            <if test="tabFlag != null and tabFlag != ''">#{tabFlag},</if>
            <if test="configModal != null and configModal != ''">#{configModal},</if>
            <if test="productInfoEtitle != null">#{productInfoEtitle},</if>
            <if test="productInfoCtitle != null and productInfoCtitle != ''">#{productInfoCtitle},</if>
            <if test="productInfoOrder != null">#{productInfoOrder},</if>
            <if test="createTime != null">#{createTime},</if>
            <if test="createBy != null">#{createBy},</if>
            <if test="updateTime != null">#{updateTime},</if>
            <if test="updateBy != null">#{updateBy},</if>
         </trim>
    </insert>

    <update id="updateHwProductInfo" parameterType="HwProductInfo">
        update hw_product_info
        <trim prefix="SET" suffixOverrides=",">
            <if test="configTypeId != null and configTypeId != ''">config_type_id = #{configTypeId},</if>
            <if test="tabFlag != null and tabFlag != ''">tab_flag = #{tabFlag},</if>
            <if test="configModal != null and configModal != ''">config_modal = #{configModal},</if>
            <if test="productInfoEtitle != null">product_info_etitle = #{productInfoEtitle},</if>
            <if test="productInfoCtitle != null and productInfoCtitle != ''">product_info_ctitle = #{productInfoCtitle},</if>
            <if test="productInfoOrder != null">product_info_order = #{productInfoOrder},</if>
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="createBy != null">create_by = #{createBy},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="updateBy != null">update_by = #{updateBy},</if>
        </trim>
        where product_info_id = #{productInfoId}
    </update>

    <delete id="deleteHwProductInfoByProductInfoId" parameterType="Long">
        delete from hw_product_info where product_info_id = #{productInfoId}
    </delete>

    <delete id="deleteHwProductInfoByProductInfoIds" parameterType="String">
        delete from hw_product_info where product_info_id in 
        <foreach item="productInfoId" collection="array" open="(" separator="," close=")">
            #{productInfoId}
        </foreach>
    </delete>




    <select id="selectHwProductInfoJoinDetailList" parameterType="HwProductInfo" resultMap="HwProductInfoHwProductInfoDetailResult">
        select a.product_info_id, a.config_type_id, a.tab_flag, a.config_modal, a.product_info_etitle, a.product_info_ctitle, a.product_info_order, a.create_time, a.create_by, a.update_time, a.update_by,
        b.product_info_detail_id as sub_product_info_detail_id, b.parent_id as sub_parent_id, b.product_info_id as sub_product_info_id, b.product_info_detail_title as sub_product_info_detail_title, b.product_info_detail_desc as sub_product_info_detail_desc, b.product_info_detail_order as sub_product_info_detail_order, b.product_info_detail_pic as sub_product_info_detail_pic, b.ancestors as sub_ancestors, b.create_time as sub_create_time, b.create_by as sub_create_by, b.update_time as sub_update_time, b.update_by as sub_update_by,
        b.config_modal AS config_model
        from hw_product_info a
        left join hw_product_info_detail b on b.product_info_id = a.product_info_id
        <where>
            <if test="configTypeId != null  and configTypeId != ''"> and a.config_type_id = #{configTypeId}</if>
            <if test="tabFlag != null  and tabFlag != ''"> and a.tab_flag = #{tabFlag}</if>
            <if test="configModal != null  and configModal != ''"> and a.config_modal = #{configModal}</if>
            <if test="productInfoEtitle != null "> and a.product_info_etitle = #{productInfoEtitle}</if>
            <if test="productInfoCtitle != null  and productInfoCtitle != ''"> and a.product_info_ctitle = #{productInfoCtitle}</if>
            <if test="productInfoOrder != null "> and a.product_info_order = #{productInfoOrder}</if>
            <if test="parentId != null"> and b.parent_id = #{parentId}</if>
        </where>
    </select>




    <sql id="selectHwProductInfoJoinVo">
        select hpi.product_info_id, hpi.config_type_id, hpi.tab_flag, hpi.config_modal, hpi.product_info_etitle, hpi.product_info_ctitle, hpi.product_info_order,
               hpi.create_time, hpi.create_by, hpi.update_time, hpi.update_by,hpct.config_type_name from hw_product_info hpi left join hw_portal_config_type hpct on hpi.config_type_id=hpct.config_type_id
    </sql>

    <select id="selectHwProductInfoJoinList" parameterType="HwProductInfo" resultMap="HwProductInfoResult">
        <include refid="selectHwProductInfoJoinVo"/>
        <where>
            <if test="configTypeId != null  and configTypeId != ''"> and hpi.config_type_id = #{configTypeId}</if>
            <if test="tabFlag != null  and tabFlag != ''"> and hpi.tab_flag = #{tabFlag}</if>
            <if test="configModal != null  and configModal != ''"> and hpi.config_modal = #{configModal}</if>
            <if test="productInfoEtitle != null "> and hpi.product_info_etitle like concat('%', #{productInfoEtitle}, '%')</if>
            <if test="productInfoCtitle != null  and productInfoCtitle != ''"> and hpi.product_info_ctitle like concat('%', #{productInfoCtitle}, '%')</if>
            <if test="productInfoOrder != null "> and hpi.product_info_order = #{productInfoOrder}</if>
        </where>
    </select>

</mapper>

ruoyi-portal/src/main/resources/mapper/portal/HwSearchMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.portal.mapper.HwSearchMapper">

    <resultMap id="SearchRawRecordResult" type="com.ruoyi.portal.domain.dto.SearchRawRecord">
        <result property="sourceType" column="source_type"/>
        <result property="bizId" column="biz_id"/>
        <result property="title" column="title"/>
        <result property="content" column="content"/>
        <result property="webCode" column="web_code"/>
        <result property="typeId" column="type_id"/>
        <result property="deviceId" column="device_id"/>
        <result property="menuId" column="menu_id"/>
        <result property="documentId" column="document_id"/>
        <result property="score" column="score"/>
        <result property="updatedAt" column="updated_at"/>
    </resultMap>

    <select id="searchByKeyword" resultMap="SearchRawRecordResult">
        SELECT *
        FROM (
            SELECT 'menu' AS source_type,
                   CAST(m.web_menu_id AS CHAR) AS biz_id,
                   m.web_menu_name AS title,
                   CONCAT(IFNULL(m.web_menu_name, ''), ' ', IFNULL(m.ancestors, '')) AS content,
                   NULL AS web_code,
                   NULL AS type_id,
                   NULL AS device_id,
                   CAST(m.web_menu_id AS CHAR) AS menu_id,
                   NULL AS document_id,
                   110 AS score,
                   m.update_time AS updated_at
            FROM hw_web_menu m
            WHERE m.is_delete = '0'
              AND (
                  m.web_menu_name LIKE CONCAT('%', #{keyword}, '%')
                  OR m.ancestors LIKE CONCAT('%', #{keyword}, '%')
              )

            UNION ALL

            SELECT 'web' AS source_type,
                   CAST(w.web_id AS CHAR) AS biz_id,
                   CONCAT('页面#', w.web_code) AS title,
                   w.web_json_string AS content,
                   CAST(w.web_code AS CHAR) AS web_code,
                   NULL AS type_id,
                   NULL AS device_id,
                   NULL AS menu_id,
                   NULL AS document_id,
                   80 AS score,
                   w.update_time AS updated_at
            FROM hw_web w
            WHERE w.is_delete = '0'
              AND w.web_json_string LIKE CONCAT('%', #{keyword}, '%')

            UNION ALL

            SELECT 'web1' AS source_type,
                   CAST(w1.web_id AS CHAR) AS biz_id,
                   CONCAT('详情#', w1.web_code, '-', w1.typeId, '-', w1.device_id) AS title,
                   w1.web_json_string AS content,
                   CAST(w1.web_code AS CHAR) AS web_code,
                   CAST(w1.typeId AS CHAR) AS type_id,
                   CAST(w1.device_id AS CHAR) AS device_id,
                   NULL AS menu_id,
                   NULL AS document_id,
                   90 AS score,
                   w1.update_time AS updated_at
            FROM hw_web1 w1
            WHERE w1.is_delete = '0'
              AND w1.web_json_string LIKE CONCAT('%', #{keyword}, '%')

            UNION ALL

            SELECT 'document' AS source_type,
                   d.document_id AS biz_id,
                   IFNULL(NULLIF(d.json, ''), d.document_id) AS title,
                   IFNULL(d.json, '') AS content,
                   d.web_code AS web_code,
                   d.type AS type_id,
                   NULL AS device_id,
                   NULL AS menu_id,
                   d.document_id AS document_id,
                   70 AS score,
                   d.update_time AS updated_at
            FROM hw_web_document d
            WHERE d.is_delete = '0'
              AND (
                  d.json LIKE CONCAT('%', #{keyword}, '%')
                  OR d.document_id LIKE CONCAT('%', #{keyword}, '%')
              )

            UNION ALL

            SELECT 'configType' AS source_type,
                   CAST(ct.config_type_id AS CHAR) AS biz_id,
                   ct.config_type_name AS title,
                   CONCAT(IFNULL(ct.config_type_name, ''), ' ', IFNULL(ct.home_config_type_name, ''), ' ', IFNULL(ct.config_type_desc, '')) AS content,
                   NULL AS web_code,
                   CAST(ct.config_type_id AS CHAR) AS type_id,
                   NULL AS device_id,
                   NULL AS menu_id,
                   NULL AS document_id,
                   65 AS score,
                   ct.update_time AS updated_at
            FROM hw_portal_config_type ct
            WHERE ct.config_type_name LIKE CONCAT('%', #{keyword}, '%')
               OR ct.home_config_type_name LIKE CONCAT('%', #{keyword}, '%')
               OR ct.config_type_desc LIKE CONCAT('%', #{keyword}, '%')
        ) s
        ORDER BY s.score DESC, s.updated_at DESC
        LIMIT 500
    </select>
</mapper>

ruoyi-portal/src/main/resources/mapper/portal/HwWebDocumentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.portal.mapper.HwWebDocumentMapper">
    
    <resultMap type="HwWebDocument" id="HwWebDocumentResult">
        <result property="documentId"    column="document_id"    />
        <result property="tenantId"    column="tenant_id"    />
        <result property="documentAddress"    column="document_address"    />
        <result property="createTime"    column="create_time"    />
        <result property="webCode"    column="web_code"    />
        <result property="secretKey"    column="secretKey"    />
        <result property="json"    column="json"    />
        <result property="type"    column="type"    />
        <result property="isDelete" column="is_delete" />
    </resultMap>

    <sql id="selectHwWebDocumentVo">
        select document_id, tenant_id, document_address, create_time, web_code, secretKey ,
               json, type,
                is_delete
        from hw_web_document
    </sql>

    <select id="selectHwWebDocumentList" parameterType="HwWebDocument" resultMap="HwWebDocumentResult">
        <include refid="selectHwWebDocumentVo"/>
        <where>
            and is_delete = '0'
            <if test="documentId != null "> and document_id = #{documentId}</if>
            <if test="tenantId != null "> and tenant_id = #{tenantId}</if>
            <if test="documentAddress != null  and documentAddress != ''"> and document_address = #{documentAddress}</if>
            <if test="webCode != null  and webCode != ''"> and web_code = #{webCode}</if>
            <if test="secretKey != null  and secretKey != ''"> and secretKey = #{secretKey}</if>
             <if test="json != null  and json != ''"> and json = #{json}</if>
              <if test="type != null  and type != ''"> and type = #{type}</if>
        </where>
    </select>
    
    <select id="selectHwWebDocumentByDocumentId" parameterType="String" resultMap="HwWebDocumentResult">
        <include refid="selectHwWebDocumentVo"/>
        where is_delete = '0' and document_id = #{documentId}
    </select>
        
    <insert id="insertHwWebDocument" parameterType="HwWebDocument" useGeneratedKeys="true" keyProperty="documentId">
        insert into hw_web_document
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="documentId != null">document_id,</if>
            <if test="tenantId != null">tenant_id,</if>
            <if test="documentAddress != null">document_address,</if>
            <if test="createTime != null">create_time,</if>
            <if test="webCode != null">web_code,</if>
            <if test="secretKey != null">secretKey,</if>
            <if test="json != null">json,</if>
            <if test="type != null">type,</if>
            is_delete,
         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="documentId != null">#{documentId},</if>
            <if test="tenantId != null">#{tenantId},</if>
            <if test="documentAddress != null">#{documentAddress},</if>
            <if test="createTime != null">#{createTime},</if>
            <if test="webCode != null">#{webCode},</if>
            <if test="secretKey != null">#{secretKey},</if>
            <if test="json != null">#{json},</if>
            <if test="type != null">#{type},</if>
            <choose>
                <when test="isDelete != null and isDelete != ''">#{isDelete},</when>
                <otherwise>'0',</otherwise>
            </choose>
         </trim>
    </insert>

    <update id="updateHwWebDocument" parameterType="HwWebDocument">
        update hw_web_document
        <trim prefix="SET" suffixOverrides=",">
            <if test="documentId != null">document_id = #{documentId},</if>
            <if test="tenantId != null">tenant_id = #{tenantId},</if>
            <if test="documentAddress != null">document_address = #{documentAddress},</if>
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="webCode != null">web_code = #{webCode},</if>
            <if test="secretKey != null">
                secretKey = <choose>
                    <when test="secretKey == ''">NULL</when>
                    <otherwise>#{secretKey}</otherwise>
                </choose>,
            </if>
            <if test="json != null">json = #{json},</if>
            <if test="type != null">type = #{type},</if>
        </trim>
        where document_id = #{documentId}
    </update>

    <update id="deleteHwWebDocumentByDocumentId" parameterType="String">
        update hw_web_document set is_delete = '1' where document_id = #{documentId}
    </update>

    <update id="deleteHwWebDocumentByDocumentIds" parameterType="String">
        update hw_web_document set is_delete = '1' where document_id in 
        <foreach item="documentId" collection="array" open="(" separator="," close=")">
            #{documentId}
        </foreach>
    </update>
</mapper>

ruoyi-portal/src/main/resources/mapper/portal/HwWebMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.portal.mapper.HwWebMapper">

    <resultMap type="HwWeb" id="HwWebResult">
        <result property="webId"    column="web_id"    />
        <result property="webJson"    column="web_json"    />
        <result property="webJsonString"    column="web_json_string"    />
        <result property="webCode"    column="web_code"    />
        <result property="isDelete" column="is_delete" />
        <result property="webJsonEnglish" column="web_json_english" />
    </resultMap>

    <sql id="selectHwWebVo">
        select web_id, web_json, web_json_string, web_code,
               web_json_english,
        is_delete 
        from hw_web
    </sql>

    <select id="selectHwWebList" parameterType="HwWeb" resultMap="HwWebResult">
        <include refid="selectHwWebVo"/>
        <where>
            and is_delete = '0'
            <if test="webId != null "> and web_id = #{webId}</if>
            <if test="webJson != null  and webJson != ''"> and web_json = #{webJson}</if>
            <if test="webJsonString != null  and webJsonString != ''"> and web_json_string = #{webJsonString}</if>
            <if test="webCode != null "> and web_code = #{webCode}</if>
             <if test="webJsonEnglish != null"> and web_json_english = #{webJsonEnglish}</if>
        </where>
    </select>

    <select id="selectHwWebByWebcode" parameterType="Long" resultMap="HwWebResult">
        <include refid="selectHwWebVo"/>
        where is_delete = '0' and web_code = #{webCode}
    </select>

    <insert id="insertHwWeb" parameterType="HwWeb" useGeneratedKeys="true" keyProperty="webId">
        insert into hw_web
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="webJson != null">web_json,</if>
            <if test="webJsonString != null">web_json_string,</if>
            <if test="webCode != null">web_code,</if>
            <if test="webJsonEnglish != null">web_json_english,</if>
            is_delete,
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="webJson != null">#{webJson},</if>
            <if test="webJsonString != null">#{webJsonString},</if>
            <if test="webCode != null">#{webCode},</if>
            <if test="webJsonEnglish != null">#{webJsonEnglish},</if>
            <choose>
                <when test="isDelete != null and isDelete != ''">#{isDelete},</when>
                <otherwise>'0',</otherwise>
            </choose>
        </trim>
    </insert>

    <update id="updateHwWeb" parameterType="HwWeb">
        update hw_web
        <trim prefix="SET" suffixOverrides=",">
            <if test="webJson != null">web_json = #{webJson},</if>
            <if test="webJsonString != null">web_json_string = #{webJsonString},</if>
<!--            <if test="webCode != null">web_code = #{webCode},</if>-->
            <if test="webJsonEnglish != null">web_json_english = #{webJsonEnglish},</if>
        </trim>
        where web_code = #{webCode}
    </update>

    <update id="deleteHwWebByWebId" parameterType="Long">
        update hw_web set is_delete = '1' where web_id = #{webId}
    </update>

    <update id="deleteHwWebByWebIds" parameterType="String">
        update hw_web set is_delete = '1' where web_id in
        <foreach item="webId" collection="array" open="(" separator="," close=")">
            #{webId}
        </foreach>
    </update>
</mapper>

ruoyi-portal/src/main/resources/mapper/portal/HwWebMapper1.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.portal.mapper.HwWebMapper1">

    <resultMap type="HwWeb1" id="HwWebResult1">
        <result property="webId"    column="web_id"    />
        <result property="webJson"    column="web_json"    />
        <result property="webJsonString"    column="web_json_string"    />
        <result property="webCode"    column="web_code"    />
        <result property="deviceId"    column="device_id"    />
        <result property="typeId"    column="typeId"    />
        <result property="isDelete" column="is_delete" />
        <result property="webJsonEnglish" column="web_json_english" />
    </resultMap>

    <sql id="selectHwWebVo">
        select web_id, web_json, web_json_string, web_code,
            device_id, typeId, web_json_english,
            is_delete
         from hw_web1
    </sql>

    <select id="selectHwWebList" parameterType="HwWeb1" resultMap="HwWebResult1">
        <include refid="selectHwWebVo"/>
        <where>
            and is_delete = '0'
            <if test="webId != null "> and web_id = #{webId}</if>
            <if test="webJson != null  and webJson != ''"> and web_json = #{webJson}</if>
            <if test="webJsonString != null  and webJsonString != ''"> and web_json_string = #{webJsonString}</if>
            <if test="webCode != null "> and web_code = #{webCode}</if>
            <if test="deviceId != null "> and device_id = #{deviceId}</if>
             <if test="typeId != null "> and typeId = #{typeId}</if>
              <if test="webJsonEnglish != null "> and web_json_english = #{webJsonEnglish}</if>
        </where>
    </select>

    <select id="selectHwWebByWebcode" parameterType="Long" resultMap="HwWebResult1">
        <include refid="selectHwWebVo"/>
        where is_delete = '0' and web_code = #{webCode}
    </select>

    <select id="selectHwWebOne" parameterType="HwWeb1" resultMap="HwWebResult1">
        <include refid="selectHwWebVo"/>
        where is_delete = '0' and web_code = #{webCode}
        and device_id = #{deviceId}
        and typeId = #{typeId}
    </select>

    <insert id="insertHwWeb" parameterType="HwWeb1" useGeneratedKeys="true" keyProperty="webId">
        insert into hw_web1
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="webJson != null">web_json,</if>
            <if test="webJsonString != null">web_json_string,</if>
            <if test="webCode != null">web_code,</if>
            <if test="deviceId != null">device_id,</if>
            <if test="typeId != null">typeId,</if>
            <if test="webJsonEnglish != null">web_json_english,</if>
            is_delete,
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="webJson != null">#{webJson},</if>
            <if test="webJsonString != null">#{webJsonString},</if>
            <if test="webCode != null">#{webCode},</if>
            <if test="deviceId != null">#{deviceId},</if>
            <if test="typeId != null">#{typeId},</if>
            <if test="webJsonEnglish != null">#{webJsonEnglish},</if>
            <choose>
                <when test="isDelete != null and isDelete != ''">#{isDelete},</when>
                <otherwise>'0',</otherwise>
            </choose>
        </trim>
    </insert>

    <update id="updateHwWeb" parameterType="HwWeb1">
        update hw_web1
        <trim prefix="SET" suffixOverrides=",">
            <if test="webJson != null">web_json = #{webJson},</if>
            <if test="webJsonString != null">web_json_string = #{webJsonString},</if>
<!--            <if test="webCode != null">web_code = #{webCode},</if>-->
<!--            <if test="deviceId != null">device_id = #{deviceId},</if>-->
<!--            <if test="typeId != null">typeId = #{typeId},</if>-->
            <if test="webJsonEnglish != null">web_json_english = #{webJsonEnglish},</if>
        </trim>
        where web_code = #{webCode}
        and device_id = #{deviceId}
        and typeId = #{typeId}
    </update>

    <update id="deleteHwWebByWebId" parameterType="Long">
        update hw_web1 set is_delete = '1' where web_id = #{webId}
    </update>

    <update id="deleteHwWebByWebIds" parameterType="String">
        update hw_web1 set is_delete = '1' where web_id in
        <foreach item="webId" collection="array" open="(" separator="," close=")">
            #{webId}
        </foreach>
    </update>
</mapper>

ruoyi-portal/src/main/resources/mapper/portal/HwWebMenuMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.portal.mapper.HwWebMenuMapper">

    <resultMap type="HwWebMenu" id="HwWebMenuResult">
        <result property="webMenuId"    column="web_menu_id"    />
        <result property="parent"    column="parent"    />
        <result property="ancestors"    column="ancestors"    />
        <result property="status"    column="status"    />
        <result property="webMenuName"    column="web_menu_name"    />
        <result property="tenantId"    column="tenant_id"    />
        <result property="webMenuPic"    column="web_menu__pic"    />
        <result property="webMenuType"    column="web_menu_type"    />
        <result property="order"    column="order"    />
        <result property="isDelete" column="is_delete" />
        <result property="webMenuNameEnglish" column="web_menu_name_english" />
    </resultMap>

    <sql id="selectHwWebMenuVo">
        select web_menu_id, parent, ancestors, status, web_menu_name, tenant_id, web_menu__pic, web_menu_type,
               order,
               web_menu_name_english,
        is_delete 
        from hw_web_menu
    </sql>

    <select id="selectHwWebMenuList" parameterType="HwWebMenu" resultMap="HwWebMenuResult">
        <include refid="selectHwWebMenuVo"/>
        <where>
            and is_delete = '0'
            <if test="parent != null "> and parent = #{parent}</if>
            <if test="ancestors != null  and ancestors != ''"> and ancestors = #{ancestors}</if>
            <if test="status != null  and status != ''"> and status = #{status}</if>
            <if test="webMenuName != null  and webMenuName != ''"> and web_menu_name like concat('%', #{webMenuName}, '%')</if>
            <if test="tenantId != null "> and tenant_id = #{tenantId}</if>
            <if test="webMenuPic != null  and webMenuPic != ''"> and web_menu__pic = #{webMenuPic}</if>
            <if test="webMenuType != null "> and web_menu_type = #{webMenuType}</if>
            <if test="order != null "> and `order` = #{order}</if>
             <if test="webMenuNameEnglish != null  and webMenuNameEnglish != ''"> and web_menu_name_english = #{webMenuNameEnglish}</if>
        </where>
        order by parent, order asc, web_menu_id asc
    </select>

    <select id="selectHwWebMenuByWebMenuId" parameterType="Long" resultMap="HwWebMenuResult">
        <include refid="selectHwWebMenuVo"/>
        where is_delete = '0' and web_menu_id = #{webMenuId}
    </select>

    <insert id="insertHwWebMenu" parameterType="HwWebMenu">
        insert into hw_web_menu
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="webMenuId != null">web_menu_id,</if>
            <if test="parent != null">parent,</if>
            <if test="ancestors != null">ancestors,</if>
            <if test="status != null">status,</if>
            <if test="webMenuName != null">web_menu_name,</if>
            <if test="tenantId != null">tenant_id,</if>
            <if test="webMenuPic != null">web_menu__pic,</if>
            <if test="webMenuType != null">web_menu_type,</if>
            <if test="order != null">`order`,</if>
            <if test="webMenuNameEnglish != null">web_menu_name_english,</if>
            is_delete,
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="webMenuId != null">#{webMenuId},</if>
            <if test="parent != null">#{parent},</if>
            <if test="ancestors != null">#{ancestors},</if>
            <if test="status != null">#{status},</if>
            <if test="webMenuName != null">#{webMenuName},</if>
            <if test="tenantId != null">#{tenantId},</if>
            <if test="webMenuPic != null">#{webMenuPic},</if>
            <if test="webMenuType != null">#{webMenuType},</if>
            <if test="order != null">#{order},</if>
            <if test="webMenuNameEnglish != null">#{webMenuNameEnglish},</if>
            <choose>
                <when test="isDelete != null and isDelete != ''">#{isDelete},</when>
                <otherwise>'0',</otherwise>
            </choose>
        </trim>
    </insert>

    <update id="updateHwWebMenu" parameterType="HwWebMenu">
        update hw_web_menu
        <trim prefix="SET" suffixOverrides=",">
            <if test="parent != null">parent = #{parent},</if>
            <if test="ancestors != null">ancestors = #{ancestors},</if>
            <if test="status != null">status = #{status},</if>
            <if test="webMenuName != null">web_menu_name = #{webMenuName},</if>
            <if test="tenantId != null">tenant_id = #{tenantId},</if>
            <if test="webMenuPic != null">web_menu__pic = #{webMenuPic},</if>
            <if test="webMenuType != null">web_menu_type = #{webMenuType},</if>
            <if test="order != null">`order` = #{order},</if>
            <if test="webMenuNameEnglish != null">web_menu_name_english = #{webMenuNameEnglish},</if>
        </trim>
        where web_menu_id = #{webMenuId}
    </update>

    <update id="deleteHwWebMenuByWebMenuId" parameterType="Long">
        update hw_web_menu set is_delete = '1' where web_menu_id = #{webMenuId}
    </update>

    <update id="deleteHwWebMenuByWebMenuIds" parameterType="String">
        update hw_web_menu set is_delete = '1' where web_menu_id in
        <foreach item="webMenuId" collection="array" open="(" separator="," close=")">
            #{webMenuId}
        </foreach>
    </update>
</mapper>

ruoyi-portal/src/main/resources/mapper/portal/HwWebMenuMapper1.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.portal.mapper.HwWebMenuMapper1">

    <resultMap type="HwWebMenu1" id="HwWebMenuResult1">
        <result property="webMenuId"    column="web_menu_id"    />
        <result property="parent"    column="parent"    />
        <result property="ancestors"    column="ancestors"    />
        <result property="status"    column="status"    />
        <result property="webMenuName"    column="web_menu_name"    />
        <result property="tenantId"    column="tenant_id"    />
        <result property="webMenuPic"    column="web_menu__pic"    />
        <result property="webMenuType"    column="web_menu_type"    />
        <result property="value" column="value" />
        <result property="isDelete" column="is_delete" />
        <result property="webMenuNameEnglish" column="web_menu_name_english" />
    </resultMap>

    <sql id="selectHwWebMenuVo">
        select web_menu_id, parent, ancestors, status, web_menu_name, tenant_id, web_menu__pic,
               value,
               web_menu_type,
               web_menu_name_english,
               is_delete 
               from hw_web_menu1
    </sql>

    <select id="selectHwWebMenuList" parameterType="HwWebMenu1" resultMap="HwWebMenuResult1">
        <include refid="selectHwWebMenuVo"/>
        <where>
            and is_delete = '0'
            <if test="parent != null "> and parent = #{parent}</if>
            <if test="ancestors != null  and ancestors != ''"> and ancestors = #{ancestors}</if>
            <if test="status != null  and status != ''"> and status = #{status}</if>
            <if test="webMenuName != null  and webMenuName != ''"> and web_menu_name like concat('%', #{webMenuName}, '%')</if>
            <if test="tenantId != null "> and tenant_id = #{tenantId}</if>
            <if test="webMenuPic != null  and webMenuPic != ''"> and web_menu__pic = #{webMenuPic}</if>
            <if test="webMenuType != null "> and web_menu_type = #{webMenuType}</if>
             <if test="value != null  and value != ''"> and value like concat('%', #{value}, '%')</if>
              <if test="webMenuNameEnglish != null  and webMenuNameEnglish != ''"> and web_menu_name_english like concat('%', #{webMenuNameEnglish}, '%')</if>
        </where>
    </select>

    <select id="selectHwWebMenuByWebMenuId" parameterType="Long" resultMap="HwWebMenuResult1">
        <include refid="selectHwWebMenuVo"/>
        where is_delete = '0' and web_menu_id = #{webMenuId}
    </select>

    <insert id="insertHwWebMenu" parameterType="HwWebMenu1">
        insert into hw_web_menu1
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="webMenuId != null">web_menu_id,</if>
            <if test="parent != null">parent,</if>
            <if test="ancestors != null">ancestors,</if>
            <if test="status != null">status,</if>
            <if test="webMenuName != null">web_menu_name,</if>
            <if test="tenantId != null">tenant_id,</if>
            <if test="webMenuPic != null">web_menu__pic,</if>
            <if test="webMenuType != null">web_menu_type,</if>
            <if test="value != null">value,</if>
            <if test="webMenuNameEnglish != null">web_menu_name_english,</if>
            is_delete,
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="webMenuId != null">#{webMenuId},</if>
            <if test="parent != null">#{parent},</if>
            <if test="ancestors != null">#{ancestors},</if>
            <if test="status != null">#{status},</if>
            <if test="webMenuName != null">#{webMenuName},</if>
            <if test="tenantId != null">#{tenantId},</if>
            <if test="webMenuPic != null">#{webMenuPic},</if>
            <if test="webMenuType != null">#{webMenuType},</if>
            <if test="value != null">#{value},</if>
            <if test="webMenuNameEnglish != null">#{webMenuNameEnglish},</if>
            <choose>
                <when test="isDelete != null and isDelete != ''">#{isDelete},</when>
                <otherwise>'0',</otherwise>
            </choose>
        </trim>
    </insert>

    <update id="updateHwWebMenu" parameterType="HwWebMenu1">
        update hw_web_menu1
        <trim prefix="SET" suffixOverrides=",">
            <if test="parent != null">parent = #{parent},</if>
            <if test="ancestors != null">ancestors = #{ancestors},</if>
            <if test="status != null">status = #{status},</if>
            <if test="webMenuName != null">web_menu_name = #{webMenuName},</if>
            <if test="tenantId != null">tenant_id = #{tenantId},</if>
            <if test="webMenuPic != null">web_menu__pic = #{webMenuPic},</if>
            <if test="webMenuType != null">web_menu_type = #{webMenuType},</if>
            <if test="value != null">value = #{value},</if>
            <if test="webMenuNameEnglish != null">web_menu_name_english = #{webMenuNameEnglish},</if>
        </trim>
        where web_menu_id = #{webMenuId}
    </update>

    <update id="deleteHwWebMenuByWebMenuId" parameterType="Long">
        update hw_web_menu1 set is_delete = '1' where web_menu_id = #{webMenuId}
    </update>

    <update id="deleteHwWebMenuByWebMenuIds" parameterType="String">
        update hw_web_menu1 set is_delete = '1' where web_menu_id in
        <foreach item="webMenuId" collection="array" open="(" separator="," close=")">
            #{webMenuId}
        </foreach>
    </update>
</mapper>