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.

80 KiB

hw-portal 官网模块说明HwWeb / HwWeb1 / HwWebDocument / HwWebMenu / HwWebMenu1

仅关注与 HwWebHwWeb1HwWebDocumentHwWebMenuHwWebMenu1 相关的代码逻辑,方便 AI 与技术人员统一阅读和分析。

0.后端代码注意事项

  • hw-portal是微服务旧项目springboot2+mybatis的某个模块直接复制过来现在是springboot3+MybatisPlus的单体新项目需要将旧项目hw-portal模块的HwWeb、HwWeb1、HwWebDocument、HwWebMenu、HwWebMenu1的后端代码逻辑全部迁移到新项目的rfid-middleware\ruoyi-modules\hw-web模块中
  • 注意只关注HwWeb、HwWeb1、HwWebDocument、HwWebMenu、HwWebMenu1
  • 要求实体类的字段类型都与旧项目一致!
  • 注意前端的判断依据大多都是code
  • 接口必须与旧项目完全一致,以方便前端直接调用!
  • 注意旧项目接口的权限控制已经全部注释掉了!
  • 要求代码逻辑不变尽量贴合现在新项目的springboot3+MybatisPlus
  • 代码的实现方式可以考虑MybatisPlus自带方法比如说增删改查或者是逻辑删除但是业务逻辑必须要一致
  • 数据库表结构中is_delete字段0表示未删除1表示已删除
  • 注意现在新项目的文件服务也已经与旧项目完全不一样了,需要匹配现有新项目!
  • 数据库表结构与BaseEntity或者TenantEntity不一致不应该继承将相关字段填入在自己实体类中即可注意@TableField(fill = FieldFill.INSERT)

1. 模块总览

  • 页面 JSON 配置

    • 表:hw_web,实体:HwWeb
    • 表:hw_web1,实体:HwWeb1
    • 作用:存储官网页面的 JSON 配置(含中英文),hw_web1hw_web 基础上增加了 deviceIdtypeId 维度,实现「页面编码 + 设备 + 类型」组合唯一。
  • 官网菜单

    • 表:hw_web_menu,实体:HwWebMenu
    • 表:hw_web_menu1,实体:HwWebMenu1
    • 作用:存储官网菜单树结构,支持多层级父子关系;其中 HwWebMenu1 相比 HwWebMenu 额外包含 valuel 字段(数据库列名为 value),用于绑定前端路由值或业务编码。
  • 资料文件(带密钥保护)

    • 表:hw_web_document,实体:HwWebDocument
    • 作用:存储资料文件的访问地址、所属页面编码、类型等,同时支持可选密钥保护(有密钥就必须验证才能拿到真实地址)。
  • 软删除统一约定

    • 所有上述表都使用 is_delete 字段做逻辑删除:
      • '0':未删除
      • '1':已删除
    • Mapper XML 中所有查询均默认附带 and is_delete = '0' 条件。

2. 页面 JSONHwWeb / HwWeb1

2.1 实体结构

  • HwWeb(表:hw_web

    • webId:主键 ID
    • webJsonJSON 内容
    • webJsonStringJSON 的字符串表示(便于展示或简单查询)
    • webCode:页面编码,作为业务主键
    • isDelete:逻辑删除标志
    • webJsonEnglish:英文 JSON 字符串
  • HwWeb1(表:hw_web1

    • HwWeb 的基础上新增:
      • deviceId:设备 ID
      • typeId:类型 ID
    • 唯一约束在服务层通过 (webCode, deviceId, typeId) 组合保证。

字段类型与数据库映射:

  • HwWeb
字段名 Java 类型 数据库列名 说明
webId Long web_id 主键 ID
webJson String web_json 页面 JSON 内容
webJsonString String web_json_string JSON 的字符串形式
webCode Long web_code 页面编码,业务主键
isDelete String is_delete 逻辑删除标志,0 未删,1 已删
webJsonEnglish String web_json_english 英文 JSON 字符串
  • HwWeb1
字段名 Java 类型 数据库列名 说明
webId Long web_id 主键 ID
webJson String web_json 页面 JSON 内容
webJsonString String web_json_string JSON 的字符串形式
webCode Long web_code 页面编码,业务主键
deviceId Long device_id 设备 ID用于区分终端
typeId Long typeId 类型 ID用于区分业务/场景
isDelete String is_delete 逻辑删除标志,0 未删,1 已删
webJsonEnglish String web_json_english 英文 JSON 字符串

2.2 Mapper & XML 行为

2.2.1 HwWebMapper + HwWebMapper.xml

  • 查询列表selectHwWebList(HwWeb hwWeb)

    • 基础 SQLselect web_id, web_json, ... from hw_web
    • 统一条件:and is_delete = '0'
    • 支持按 webIdwebJsonwebJsonStringwebCodewebJsonEnglish 等过滤。
  • 单条查询selectHwWebByWebcode(Long webCode)

    • 在基础 SQL 上追加:where is_delete = '0' and web_code = #{webCode}
  • 插入insertHwWeb(HwWeb hwWeb)

    • 按字段非空插入,并默认 is_delete = '0'
  • 更新updateHwWeb(HwWeb hwWeb)

    • 只允许更新 web_jsonweb_json_stringweb_json_english,不更新 web_code 和主键。
    • 更新条件为:where web_code = #{webCode}
  • 删除 / 批量删除

    • deleteHwWebByWebId(Long webId)update hw_web set is_delete = '1' where web_id = #{webId}
    • deleteHwWebByWebIds(Long[] webIds)update ... where web_id in (...),同样为逻辑删除。

2.2.2 HwWebMapper1 + HwWebMapper1.xml

  • 行为与 HwWebMapper 类似,差异:
    • 额外字段 device_idtypeIdweb_json_english
    • selectHwWebOne(HwWeb1 hwWeb1):按 web_code + device_id + typeId 精确查询一条记录。
    • updateHwWeb(HwWeb1 hwWeb1) 的 where 条件为:
      • where web_code = #{webCode} and device_id = #{deviceId} and typeId = #{typeId}

2.3 Service 接口与实现

2.3.1 接口:IHwWebService / IHwWebService1

  • 统一约定的方法:
    • selectHwWebByWebcode(Long webCode)
    • selectHwWebList(...)
    • insertHwWeb(...)
    • updateHwWeb(...)
    • deleteHwWebByWebIds(Long[] webIds)
    • deleteHwWebByWebId(Long webId)
    • IHwWebService1 额外提供:selectHwWebOne(HwWeb1 hwWeb1)

2.3.2 实现:HwWebServiceImpl(基于 hw_web

  • 查询

    • selectHwWebByWebcode:直接委托 MapperwebCode 进行精确查询。
    • selectHwWebList:委托 Mapper按入参条件筛选列表。
  • 新增

    • insertHwWeb:调用 Mapper 插入,未做额外业务校验。
  • 更新(逻辑:版本化替换)

    • updateHwWeb(HwWeb hwWeb)
      • 构造 codeWeb,只设置 webCode
      • 调用 selectHwWebList(codeWeb) 查出该编码下所有未删除记录。
      • 若存在:
        • 提取这些记录的 webId,组装为数组。
        • 调用 deleteHwWebByWebIds 对这些旧记录做「逻辑删除」。
      • 为新纪录显式设置 isDelete = "0"
      • 调用 insertHwWeb(hwWeb) 插入一条新的记录(而不是更新原来的主键)。
    • 效果
      • 每次更新页面 JSON都会为同一个 webCode 生成一个新版本的记录,同时逻辑删除旧版本。
      • 可保留历史记录(在数据库中),但系统只会查询 is_delete = '0' 的最新版本。
  • 删除

    • deleteHwWebByWebIds / deleteHwWebByWebId:通过 Mapper 将记录逻辑删除。

2.3.3 实现:HwWebServiceImpl1(基于 hw_web1

  • HwWebServiceImpl 基本一致,差异在于唯一键逻辑

    • 更新时构造 codeWeb
      • codeWeb.setWebCode(hwWeb1.getWebCode())
      • codeWeb.setTypeId(hwWeb1.getTypeId())
      • codeWeb.setDeviceId(hwWeb1.getDeviceId())
    • 调用 selectHwWebList(codeWeb) 按「页面编码 + 设备 + 类型」三元组过滤。
    • 若存在老记录,同样调用 deleteHwWebByWebIds 做逻辑删除,然后插入一条新的记录,并设置 isDelete = "0"
  • 这样保证了 (webCode, deviceId, typeId) 组合在「未删除记录」中唯一,并且每次更新产生新版本。

2.4 ControllerHwWebController

基路径:/hwWeb

  • GET /hwWeb/list

    • 入参:HwWeb(作为查询条件)。
    • 调用:hwWebService.selectHwWebList(hwWeb)
    • 返回:TableDataInfo(分页表格数据)。
  • POST /hwWeb/export

    • 导出 JSON 配置列表到 Excel使用 ExcelUtil
  • GET /hwWeb/{webCode}

    • 通过页面编码 webCode 查询单条 JSON 配置。
  • POST /hwWeb

    • 新增 JSON 配置,直接调用 insertHwWeb
  • PUT /hwWeb

    • 更新 JSON 配置,调用 updateHwWeb
      • 实际为「逻辑删除旧版本 + 插入新版本」。
  • DELETE /hwWeb/{webIds}

    • 批量逻辑删除。
  • GET /hwWeb/getHwWebList

    • 返回 JSON 配置列表,包一层 AjaxResult.success(...)

3. 官网菜单HwWebMenu / HwWebMenu1

3.1 实体结构

两者都继承自 TreeEntity,支持树形结构字段:ancestorschildren 等。

  • 公共字段HwWebMenuHwWebMenu1 均有):

    • webMenuId:菜单主键 ID
    • parent:父节点 ID根节点为 null0
    • status:状态
    • webMenuName:菜单名称
    • tenantId:租户 ID
    • webMenuPic:图片地址
    • webMenuType:菜单类型
    • isDelete:逻辑删除标志
    • webMenuNameEnglish:英文名称
  • HwWebMenu1 特有字段

    • valuel:对应数据库中的 value 字段(字段名有一处 valuel,应理解为 value用于携带菜单值如路由或业务键

字段类型与数据库列映射:

  • HwWebMenu
字段名 Java 类型 数据库列名 说明
webMenuId Long web_menu_id 菜单主键 ID
parent Long parent 父节点 ID根节点为 0 或 NULL
status String status 状态
webMenuName String web_menu_name 菜单名称
tenantId Long tenant_id 租户 ID
webMenuPic String web_menu__pic 图片地址
webMenuType Long web_menu_type 菜单类型
isDelete String is_delete 逻辑删除标志,0 未删,1 已删
webMenuNameEnglish String web_menu_name_english 英文菜单名称
  • HwWebMenu1
字段名 Java 类型 数据库列名 说明
webMenuId Long web_menu_id 菜单主键 ID
parent Long parent 父节点 ID根节点为 0 或 NULL
status String status 状态
webMenuName String web_menu_name 菜单名称
tenantId Long tenant_id 租户 ID
webMenuPic String web_menu__pic 图片地址
webMenuType Long web_menu_type 菜单类型
valuel String value 菜单绑定值(如路由、业务编码);实体字段名为 valuel
isDelete String is_delete 逻辑删除标志,0 未删,1 已删
webMenuNameEnglish String web_menu_name_english 英文菜单名称

3.2 Mapper & XML 行为

3.2.1 HwWebMenuMapper / HwWebMenuMapper.xml

  • 查询列表 selectHwWebMenuList(HwWebMenu hwWebMenu)

    • 统一条件:and is_delete = '0'
    • 支持按 parentancestorsstatuswebMenuName (like)tenantIdwebMenuPicwebMenuTypewebMenuNameEnglish (like) 等过滤。
  • 单条查询 selectHwWebMenuByWebMenuId(Long webMenuId):按主键 ID + is_delete = '0' 查询。

  • 插入 / 更新 / 删除:

    • 插入时按字段非空写入,并默认 is_delete = '0'
    • 更新仅更新业务字段,不改变 is_delete
    • 删除/批量删除采用 update ... set is_delete = '1' 实现软删除。

3.2.2 HwWebMenuMapper1 / HwWebMenuMapper1.xml

  • HwWebMenuMapper 基本一致,差异:
    • 多了 value 字段(对应实体的 valuel)。
    • 查询列表时可按 value like 模糊匹配。

3.3 Service菜单树构建算法

HwWebMenuServiceImplHwWebMenuServiceImpl1 的结构几乎一致,只是实体类型和 Mapper 不同。核心逻辑:

3.3.1 列表 & 新增/修改/删除

  • selectHwWebMenuList:直接委托 Mapper对应接口方法。

  • 新增insertHwWebMenu

    • 调用 Mapper 插入,未做额外业务校验。
  • 更新updateHwWebMenu

    • 调用 Mapper 更新,仅更新业务字段,不改变 is_delete
  • 删除deleteHwWebMenuByWebMenuId / deleteHwWebMenuByWebMenuIds

    • 调用 Mapper 删除/批量删除,实现软删除。

3.3.2 构建菜单树:selectMenuTree + buildWebMenuTree

  • 入口

    • selectMenuTree(HwWebMenu hwWebMenu) / selectMenuTree(HwWebMenu1 hwWebMenu1)
      • 先查询平铺列表:hwWebMenuMapper.selectHwWebMenuList(...)
      • 调用 buildWebMenuTree(List<...> menus) 构造树结构。
  • buildWebMenuTree 逻辑(两者完全类似):

    1. 收集所有菜单的 webMenuId 到列表 tempList
    2. 遍历每个菜单 menu
      • 若满足以下任一条件,则视为根节点:
        • menu.getParent() == null
        • menu.getParent() == 0L
        • tempList 中不包含 menu.getParent()(父节点不在当前集合中)
      • 对于根节点调用 recursionFn(menus, menu) 递归设置子节点,并加入返回列表 returnList
    3. 若最终 returnList 为空(极端情况),则直接返回原始 menus
  • recursionFn 递归设置子节点

    • 通过 getChildList(list, t) 获取所有 parent == t.webMenuId 的子菜单列表。
    • 调用 t.setChildren(childList) 建立树结构。
    • 对每个子节点 tChild,若 hasChild(list, tChild) 返回 true,则继续递归。
  • getChildList / hasChild

    • getChildList 遍历整张平铺列表,筛选 parent 等于当前节点 ID 的记录。
    • hasChild 则判断 getChildList 返回列表是否为空。
    • 使用 StringUtils.isNotNull(n.getParent()) 判断父节点不为空,提高健壮性。

前端只需要调用 /hwWebMenu/selectMenuTree/hwWebMenu1/selectMenuTree,即可得到带 children 字段的完整菜单树结构。

3.4 Controller菜单接口

3.4.1 旧菜单:HwWebMenuController/hwWebMenu

  • GET /hwWebMenu/list:返回菜单列表(平铺)。

  • POST /hwWebMenu/export:导出 Excel。

  • GET /hwWebMenu/{webMenuId}:按 ID 查询明细。

  • POST /hwWebMenu:新增菜单。

  • PUT /hwWebMenu:修改菜单。

  • DELETE /hwWebMenu/{webMenuIds}:批量删除(软删除)。

  • GET /hwWebMenu/selectMenuTree:返回菜单树。

3.4.2 新菜单:HwWebMenuController1/hwWebMenu1

  • HwWebMenuController 完全对齐,只是实体类型换成 HwWebMenu1,以及调用 IHwWebMenuService1

4. 资料文件与密钥访问HwWebDocument

4.1 实体结构:HwWebDocument(表:hw_web_document

  • documentId:主键(String 类型)。
  • tenantId:租户 ID。
  • documentAddress真实文件存储地址URL 或路径)。
  • webCode:页面编码,用于和页面/菜单做关联。
  • secretKey:访问密钥。
    • 使用 @JsonProperty(access = WRITE_ONLY),序列化时不会返回给前端。
  • json:附加 JSON 信息(例如文件元数据)。
  • type:文件类型。(如 pdf、doc 等)
  • isDelete:逻辑删除标志。
  • 衍生方法:getHasSecret() 返回是否配置了密钥(用于前端判断是否需要弹出输入密钥的对话框)。

字段类型与数据库列映射:

字段名 Java 类型 数据库列名 说明
documentId String document_id 主键 ID字符串类型
tenantId Long tenant_id 租户 ID
documentAddress String document_address 文件存储地址URL 或路径)
webCode String web_code 页面编码,用于连表或关联页面
secretKey String secretKey 访问密钥(仅写入,序列化时不返回)
json String json 附加 JSON 信息(如文件元数据)
type String type 文件类型(如 pdf、doc
isDelete String is_delete 逻辑删除标志,0 未删,1 已删

4.2 Mapper & XML 行为

  • 列表查询 selectHwWebDocumentList

    • 强制 and is_delete = '0'
    • 支持按 documentIdtenantIddocumentAddresswebCodesecretKeyjsontype 等过滤。
  • 单条查询 selectHwWebDocumentByDocumentId:按主键 + is_delete = '0' 查询。

  • 插入 insertHwWebDocument

    • 按字段非空插入,并默认 is_delete = '0'
  • 更新 updateHwWebDocument 的特殊处理:

    • secretKey 字段使用:
      <if test="secretKey != null">
          secretKey =
            <choose>
              <when test="secretKey == ''">NULL</when>
              <otherwise>#{secretKey}</otherwise>
            </choose>,
      </if>
      
    • 配合 Service 层的「null 转空串」逻辑,实现:
      • 前端不传或传 null:认为要清空数据库中的密钥(置为 NULL)。
      • 前端传非空字符串:更新为新的密钥。
  • 删除 / 批量删除:

    • deleteHwWebDocumentByDocumentId / deleteHwWebDocumentByDocumentIds:逻辑删除(is_delete = '1')。

4.3 Service 实现:HwWebDocumentServiceImpl

  • 查询/列表/删除:直接委托 Mapper对应接口方法。

  • 新增insertHwWebDocument

    • 在插入前设置 createTime = DateUtils.getNowDate()
  • 更新updateHwWebDocument

    • 如果 hwWebDocument.getSecretKey() == null,则强制 setSecretKey("")
      • 触发 Mapper 中 <if test="secretKey != null"> 条件。
      • 在 XML 中根据空串设置数据库列为 NULL,从而清空密钥
    • 若前端传入非空密钥字符串,则按正常更新覆盖原密钥。
  • 密钥验证与安全地址获取verifyAndGetDocumentAddress(String documentId, String providedKey)

    1. 根据 documentId 查询文档,若为空:抛出 ServiceException("文件不存在")
    2. 取出 secretKeydocumentAddress
    3. secretKey 为空或空白:
      • 说明此文件不需要密钥,直接返回 documentAddress
    4. secretKey 非空:
      • 将入参 providedKey 去空格;若为空:抛出 ServiceException("密钥不能为空")
      • secretKey.trim().equals(trimmedProvided):返回 documentAddress
      • 否则抛出 ServiceException("密钥错误")

因为这里抛出的都是 ServiceExceptionController 层可统一捕获并将 e.getMessage() 作为错误提示返回给前端。

4.4 ControllerHwWebDocumentController/hwWebDocument

  • GET /hwWebDocument/list

    • 调用 startPage() 分页。
    • 查询列表后,对每个 HwWebDocument doc 做二次处理:
      • doc.setSecretKey(null):隐藏密钥字段。
      • doc.getHasSecret()truedoc.setDocumentAddress(null),隐藏真实文件地址,只暴露「是否加密」。
    • 通过 getDataTable(list) 返回分页数据。
  • POST /hwWebDocument/export

    • 导出列表到 Excel。
  • GET /hwWebDocument/{documentId}

    • 查询单条记录,并同样隐藏密钥字段;如果有密钥,也会隐藏 documentAddress
  • POST /hwWebDocument

    • 新增文档记录。
  • PUT /hwWebDocument

    • 修改文档记录,调用 updateHwWebDocument。通过 Service + XML 的联合逻辑实现「设置/修改/清空密钥」。
  • DELETE /hwWebDocument/{documentIds}

    • 批量逻辑删除。
  • POST /hwWebDocument/getSecureDocumentAddress

    • 入参:SecureDocumentRequest(包含 documentIdprovidedKey)。
    • 调用 hwWebDocumentService.verifyAndGetDocumentAddress(...)
      • 成功:返回真实 documentAddress
      • 失败:捕获异常,返回 error(e.getMessage()),前端可展示友好提示(文件不存在 / 密钥不能为空 / 密钥错误等)。

5. 典型业务流程梳理

5.1 更新页面 JSONHwWeb/HwWeb1

  1. 后台管理前端提交新的 JSON 配置到:
    • PUT /hwWeb(基于 hw_web),或
    • PUT /hwWeb1 对应的 Controller若有对应 HwWebServiceImpl1)。
  2. Service 层根据页面编码(以及 deviceIdtypeId)查询已存在记录。
  3. 将旧记录全部逻辑删除(is_delete = '1')。
  4. 插入一条新记录,isDelete = '0'
  5. 前端访问页面时,只会根据编码查询到最新一条记录。

5.2 构建官网菜单树HwWebMenu/HwWebMenu1

  1. 前端调用:
    • 旧菜单:GET /hwWebMenu/selectMenuTree
    • 新菜单:GET /hwWebMenu1/selectMenuTree
  2. Service 调用 Mapper 查询 平铺列表(均为 is_delete = '0' 的记录)。
  3. 通过 buildWebMenuTreeparent 字段递归构建树形结构:
    • 识别所有根节点(parent == null/0 或父节点不在列表中)。
    • 递归为每个节点挂接 children
  4. 返回给前端一个包含 children 的树形菜单结构,用于渲染导航栏或侧边栏。

5.3 受密钥保护的文件访问HwWebDocument

  1. 后台配置文件记录时可以选择是否设置 secretKey
    • 不设置:文件公开可访问。
    • 设置:文件地址将被后端隐藏,需要密钥校验。
  2. 前端先调用 GET /hwWebDocument/listGET /hwWebDocument/{documentId} 获取文件列表/详情:
    • 只会看到 hasSecret(通过 getHasSecret() 间接体现),看不到真实地址。
  3. 用户在前端输入密钥后,前端调用:
    • POST /hwWebDocument/getSecureDocumentAddress,携带 documentIdprovidedKey
  4. Service 层校验密钥:
    • 无密钥:直接返回地址。
    • 密钥为空:抛错 "密钥不能为空"
    • 密钥不匹配:抛错 "密钥错误"
  5. 前端拿到真实地址后,可发起真正的文件下载/打开请求。

6. 核心源码Controller + Service 实现)

以下为与 HwWeb / HwWeb1 / HwWebDocument / HwWebMenu / HwWebMenu1 强相关的控制层和服务实现类的完整源码,方便 AI 与人工检索、分析。实体类、接口与 Mapper XML 已在上文详细说明,可在 IDE 中直接定位查看原文件。

6.1 Controller 源码

6.1.1 HwWebController

package com.ruoyi.portal.controller;

import java.util.List;
import java.io.IOException;
import javax.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.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.portal.domain.HwWeb;
import com.ruoyi.portal.service.IHwWebService;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.page.TableDataInfo;

/**
 * haiwei官网jsonController
 * 
 * @author ruoyi
 * @date 2025-08-18
 */
@RestController
@RequestMapping("/hwWeb")
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)
    @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)
    @PostMapping
    public AjaxResult add(@RequestBody HwWeb hwWeb)
    {
        return toAjax(hwWebService.insertHwWeb(hwWeb));
    }

    /**
     * 修改haiwei官网json
     */
    //@RequiresPermissions("portalhwWeb:edit")
    //@Log(title = "haiwei官网json", businessType = BusinessType.UPDATE)
    @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)
	@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)) ;
    }

}

6.1.2 HwWebMenuController

package com.ruoyi.portal.controller;

import java.util.List;
import java.io.IOException;
import javax.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.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.portal.domain.HwWebMenu;
import com.ruoyi.portal.service.IHwWebMenuService;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.utils.poi.ExcelUtil;

/**
 * haiwei官网菜单Controller
 *
 * @author zch
 * @date 2025-08-18
 */
@RestController
@RequestMapping("/hwWebMenu")
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)
    @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)
    @PostMapping
    public AjaxResult add(@RequestBody HwWebMenu hwWebMenu)
    {
        return toAjax(hwWebMenuService.insertHwWebMenu(hwWebMenu));
    }

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

    /**
     * 删除haiwei官网菜单
     */
    //@RequiresPermissions("portalhwWebMenu:remove")
    //@Log(title = "haiwei官网菜单", businessType = BusinessType.DELETE)
    @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));
    }
}

6.1.3 HwWebMenuController1

package com.ruoyi.portal.controller;

import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.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 javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * haiwei官网菜单Controller
 *
 * @author zch
 * @date 2025-08-18
 */
@RestController
@RequestMapping("/hwWebMenu1")
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)
    @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)
    @PostMapping
    public AjaxResult add(@RequestBody HwWebMenu1 hwWebMenu1)
    {
        return toAjax(hwWebMenuService1.insertHwWebMenu(hwWebMenu1));
    }

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

    /**
     * 删除haiwei官网菜单
     */
    //@RequiresPermissions("portalhwWebMenu:remove")
    //@Log(title = "haiwei官网菜单", businessType = BusinessType.DELETE)
    @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));
    }
}

6.1.4 HwWebDocumentController

package com.ruoyi.portal.controller;

import java.util.List;
import java.io.IOException;
import javax.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.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.portal.domain.HwWebDocument;
import com.ruoyi.portal.service.IHwWebDocumentService;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.page.TableDataInfo;

/**
 * Hw资料文件Controller
 * 
 * @author zch
 * @date 2025-09-22
 */
@RestController
@RequestMapping("/hwWebDocument")
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)
    @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)
    @PostMapping
    public AjaxResult add(@RequestBody HwWebDocument hwWebDocument)
    {
        return toAjax(hwWebDocumentService.insertHwWebDocument(hwWebDocument));
    }

    /**
     * 修改Hw资料文件
     */
//    @RequiresPermissions("portal:hwWebDocument:edit")
    //@Log(title = "Hw资料文件", businessType = BusinessType.UPDATE)
    @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)
	@DeleteMapping("/{documentIds}")
    public AjaxResult remove(@PathVariable String[] documentIds)
    {
        return toAjax(hwWebDocumentService.deleteHwWebDocumentByDocumentIds(documentIds));
    }

	    /**
     * 获取安全文件地址
     */
//    @RequiresPermissions("portal:hwWebDocument:query")
    //@Log(title = "获取安全文件地址", businessType = BusinessType.OTHER)
    @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());
        }
    }

}

6.2 Service 实现源码

6.2.1 HwWebServiceImpl

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 org.springframework.transaction.annotation.Transactional;

/**
 * haiwei官网jsonService业务层处理
 * 
 * @author ruoyi
 * @date 2025-08-18
 */
@Service
public class HwWebServiceImpl implements IHwWebService 
{
    @Autowired
    private HwWebMapper hwWebMapper;

    /**
     * 查询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)
    {
        return hwWebMapper.insertHwWeb(hwWeb);
    }

    /**
     * 修改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");
        return hwWebMapper.insertHwWeb(hwWeb);
    }

    /**
     * 批量删除haiwei官网json
     * 
     * @param webIds 需要删除的haiwei官网json主键
     * @return 结果
     */
    @Override
    public int deleteHwWebByWebIds(Long[] webIds)
    {
        return hwWebMapper.deleteHwWebByWebIds(webIds);
    }

    /**
     * 删除haiwei官网json信息
     * 
     * @param webId haiwei官网json主键
     * @return 结果
     */
    @Override
    public int deleteHwWebByWebId(Long webId)
    {
        return hwWebMapper.deleteHwWebByWebId(webId);
    }
}

6.2.2 HwWebServiceImpl1

package com.ruoyi.portal.service.impl;


import com.ruoyi.portal.mapper.HwWebMapper1;
import com.ruoyi.portal.service.IHwWebService1;
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
{
    @Autowired
    private HwWebMapper1 hwWebMapper1;

    /**
     * 查询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)
    {
        return hwWebMapper1.insertHwWeb(hwWeb1);
    }

    /**
     * 修改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");
        return hwWebMapper1.insertHwWeb(hwWeb1);
    }

    /**
     * 批量删除haiwei官网json
     * 
     * @param webIds 需要删除的haiwei官网json主键
     * @return 结果
     */
    @Override
    public int deleteHwWebByWebIds(Long[] webIds)
    {
        return hwWebMapper1.deleteHwWebByWebIds(webIds);
    }

    /**
     * 删除haiwei官网json信息
     * 
     * @param webId haiwei官网json主键
     * @return 结果
     */
    @Override
    public int deleteHwWebByWebId(Long webId)
    {
        return hwWebMapper1.deleteHwWebByWebId(webId);
    }
}

6.2.3 HwWebMenuServiceImpl

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.core.utils.StringUtils;
import com.ruoyi.portal.domain.HwProductInfoDetail;
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
{
    @Autowired
    private HwWebMenuMapper hwWebMenuMapper;

    /**
     * 查询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)
    {
        return hwWebMenuMapper.insertHwWebMenu(hwWebMenu);
    }

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

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

    /**
     * 删除haiwei官网菜单信息
     *
     * @param webMenuId haiwei官网菜单主键
     * @return 结果
     */
    @Override
    public int deleteHwWebMenuByWebMenuId(Long webMenuId)
    {
        return hwWebMenuMapper.deleteHwWebMenuByWebMenuId(webMenuId);
    }

/**
     * 构建前端所需要树结构(根据传入的平铺菜单列表构造树)
     *
     * @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();
    }
}

6.2.4 HwWebMenuServiceImpl1

package com.ruoyi.portal.service.impl;

import com.ruoyi.common.core.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();
    }
}

6.2.5 HwWebDocumentServiceImpl

package com.ruoyi.portal.service.impl;

import java.util.List;

import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.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.IHwWebDocumentService;

/**
 * Hw资料文件Service业务层处理
 * 
 * @author zch
 * @date 2025-09-22
 */
@Service
public class HwWebDocumentServiceImpl implements IHwWebDocumentService 
{
    @Autowired
    private HwWebDocumentMapper hwWebDocumentMapper;

    /**
     * 查询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());
        return hwWebDocumentMapper.insertHwWebDocument(hwWebDocument);
    }

    /**
     * 修改Hw资料文件
     * 
     * @param hwWebDocument Hw资料文件
     * @return 结果
     */
    @Override
    public int updateHwWebDocument(HwWebDocument hwWebDocument)
    {
        // 特殊处理 secretKey前端不传或传 null 时清空数据库密钥
        // 将 null 转换为空字符串,触发 Mapper 更新条件
        if (hwWebDocument.getSecretKey() == null) {
            hwWebDocument.setSecretKey("");
        }
        
        return hwWebDocumentMapper.updateHwWebDocument(hwWebDocument);
    }

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

    /**
     * 删除Hw资料文件信息
     * 
     * @param documentId Hw资料文件主键
     * @return 结果
     */
    @Override
    public int deleteHwWebDocumentByDocumentId(String documentId)
    {
        return hwWebDocumentMapper.deleteHwWebDocumentByDocumentId(documentId);
    }

    @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("密钥错误");
        }

}

6.5 Mapper XML 源码

本节保留 5 个模块对应的 MyBatis Mapper XML 全量源码,便于直接查看 SQL、结果映射与软删除实现细节。

6.5.1 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>

6.5.2 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>

6.5.3 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>

6.5.4 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="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,
               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="webMenuNameEnglish != null  and webMenuNameEnglish != ''"> and web_menu_name_english = #{webMenuNameEnglish}</if>
        </where>
    </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="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="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="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>

6.5.5 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>