Browse Source

feat(tenant): 添加在线表单按钮权限控制功能

- 新增 FormButtonPermissionChecker 接口定义按钮权限检查器
- 实现 FormButtonPermissionCheckerImpl 提供按钮权限校验逻辑
- 创建 RoleFormButton 实体映射角色表单按钮权限配置表
- 定义 IRoleFormButtonService 接口及 RoleFormButtonServiceImpl 实现类
- 添加 RoleFormButtonController 控制器提供按钮权限配置接口
- 创建 RoleFormButtonDto 数据传输对象用于按钮权限配置
- 实现 RoleFormButtonMapper 数据访问层及对应的 XML 映射文件
- 开发 WidgetJsonButtonParser 工具类解析表单中的按钮配置
- 提供 VO 对象 RoleFormButtonVo 用于数据展示
- 实现批量保存和查询按钮权限配置的功能
- 添加按角色 ID 查询和删除相关权限配置的方法
feature/form-permission-control
chenchuchuan 3 weeks ago
parent
commit
35ee89c750
  1. 105
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/RoleFormButtonController.java
  2. 23
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/RoleFormButtonMapper.java
  3. 21
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/RoleFormButtonMapper.xml
  4. 35
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/RoleFormButtonDto.java
  5. 69
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/RoleFormButton.java
  6. 69
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/IRoleFormButtonService.java
  7. 84
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/FormButtonPermissionCheckerImpl.java
  8. 182
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/RoleFormButtonServiceImpl.java
  9. 93
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/util/WidgetJsonButtonParser.java
  10. 17
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/vo/RoleFormButtonVo.java
  11. 20
      common/common-online/src/main/java/apelet/common/online/service/FormButtonPermissionChecker.java

105
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/RoleFormButtonController.java

@ -0,0 +1,105 @@ @@ -0,0 +1,105 @@
package apelet.tenantadmin.tenant.controller;
import apelet.common.core.annotation.MyRequestBody;
import apelet.common.core.constant.ErrorCodeEnum;
import apelet.common.core.object.*;
import apelet.common.core.util.MyCommonUtil;
import apelet.common.core.util.MyPageUtil;
import apelet.common.log.annotation.OperationLog;
import apelet.common.log.model.constant.SysOperationLogType;
import apelet.tenantadmin.tenant.dto.RoleFormButtonDto;
import apelet.tenantadmin.tenant.model.RoleFormButton;
import apelet.tenantadmin.tenant.service.IRoleFormButtonService;
import com.github.pagehelper.page.PageMethod;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* 角色-表单按钮权限控制器
*
* @author chenchuchuan
* @date 2026-07-17
*/
@RestController
@RequestMapping("/tenantadmin/tenant/roleFormButton")
public class RoleFormButtonController {
@Autowired
private IRoleFormButtonService service;
/**
* 查询指定角色+表单的按钮权限配置
* 返回表单中所有开启的按钮 + 每个按钮是否已勾选
*
* @param roleId 角色ID必填
* @param formId 在线表单ID必填
* @return 包含 formId, roleId, id, buttonList[{name, checked}]
*/
@GetMapping("/getButtonConfig")
public ResponseResult<Map<String, Object>> getButtonConfig(
@RequestParam Long roleId,
@RequestParam Long formId) {
if (MyCommonUtil.existBlankArgument(roleId, formId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
Map<String, Object> result = service.getButtonConfigVo(roleId, formId);
return ResponseResult.success(result);
}
/**
* 批量保存角色+表单的按钮权限配置新增或更新
*
* @param dtoList 列表每个元素包含 roleId必填, formId必填, id编辑时传, buttonList
* @return 应答结果
*/
@OperationLog(type = SysOperationLogType.ADD)
@PostMapping("/saveButtonConfig")
public ResponseResult<Void> saveButtonConfig(
@MyRequestBody List<RoleFormButtonDto> dtoList) {
if (dtoList == null || dtoList.isEmpty()) {
return ResponseResult.error(
ErrorCodeEnum.ARGUMENT_NULL_EXIST, "数据验证失败,按钮配置列表不能为空!");
}
CallResult result = service.batchSaveButtonConfig(dtoList);
if (!result.isSuccess()) {
return ResponseResult.error(
ErrorCodeEnum.DATA_VALIDATED_FAILED, result.getErrorMessage());
}
return ResponseResult.success();
}
/**
* 根据角色ID查询该角色下所有绑定的按钮权限配置列表
*
* @param roleId 角色ID
* @return 按钮权限配置列表
*/
@GetMapping("/listByRoleId")
public ResponseResult<List<RoleFormButton>> listByRoleId(
@RequestParam Long roleId) {
if (MyCommonUtil.existBlankArgument(roleId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
return ResponseResult.success(service.listByRoleId(roleId));
}
/**
* 分页查询按钮权限配置列表
*/
@PostMapping("/list")
public ResponseResult<MyPageData<?>> list(
@MyRequestBody RoleFormButton filter,
@MyRequestBody MyOrderParam orderParam,
@MyRequestBody MyPageParam pageParam) {
if (pageParam != null) {
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize());
}
List<RoleFormButton> list = service.getListByFilter(
filter, MyOrderParam.buildOrderBy(orderParam, RoleFormButton.class));
return ResponseResult.success(
MyPageUtil.makeResponseData(list, RoleFormButton.INSTANCE));
}
}

23
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/RoleFormButtonMapper.java

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
package apelet.tenantadmin.tenant.dao;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.tenantadmin.tenant.model.RoleFormButton;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 角色-表单按钮权限配置数据访问操作接口
*
* @author chenchuchuan
* @date 2026-07-17
*/
public interface RoleFormButtonMapper extends BaseDaoMapper<RoleFormButton> {
/**
* 分页条件查询
*/
List<RoleFormButton> getListByFilter(
@Param("filter") RoleFormButton filter,
@Param("orderBy") String orderBy);
}

21
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/RoleFormButtonMapper.xml

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
<?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="apelet.tenantadmin.tenant.dao.RoleFormButtonMapper">
<select id="getListByFilter"
resultType="apelet.tenantadmin.tenant.model.RoleFormButton">
SELECT * FROM xy_sys_role_form_button
WHERE 1=1
<if test="filter.roleId != null">
AND role_id = #{filter.roleId}
</if>
<if test="filter.formId != null">
AND form_id = #{filter.formId}
</if>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
</mapper>

35
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/RoleFormButtonDto.java

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
package apelet.tenantadmin.tenant.dto;
import lombok.Data;
import java.util.List;
/**
* 角色表单按钮权限保存入参
*
* @author chenchuchuan
* @date 2026-07-17
*/
@Data
public class RoleFormButtonDto {
/** 角色ID(必填) */
private Long roleId;
/** 表单ID(必填) */
private Long formId;
/** 主键ID(编辑时传,新增时不传) */
private Long id;
/** 按钮勾选列表 */
private List<ButtonItem> buttonList;
@Data
public static class ButtonItem {
/** 按钮名称 */
private String name;
/** 是否勾选 */
private Boolean checked;
}
}

69
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/RoleFormButton.java

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
package apelet.tenantadmin.tenant.model;
import apelet.common.core.base.mapper.BaseModelMapper;
import apelet.common.core.base.model.BaseModel;
import apelet.common.core.validator.UpdateGroup;
import apelet.tenantadmin.tenant.vo.RoleFormButtonVo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;
/**
* 角色-表单按钮权限配置实体对象
*
* @author chenchuchuan
* @date 2026-07-17
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("xy_sys_role_form_button")
public class RoleFormButton extends BaseModel implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id")
@NotNull(message = "数据验证失败,id不能为空!", groups = {UpdateGroup.class})
private Long id;
/** 角色ID */
@TableField(value = "role_id")
@NotNull(message = "数据验证失败,角色ID不能为空!")
private Long roleId;
/** 在线表单ID */
@TableField(value = "form_id")
@NotNull(message = "数据验证失败,表单ID不能为空!")
private Long formId;
/** 按钮配置JSON */
@TableField(value = "button_config")
private String buttonConfig;
@TableField(value = "create_by")
private String createBy;
@TableField(value = "create_time")
private Date createTime;
@TableField(value = "update_by")
private String updateBy;
@TableField(value = "update_time")
private Date updateTime;
@Mapper
public interface RoleFormButtonModelMapper
extends BaseModelMapper<RoleFormButtonVo, RoleFormButton> {
}
public static final RoleFormButtonModelMapper INSTANCE =
Mappers.getMapper(RoleFormButtonModelMapper.class);
}

69
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/IRoleFormButtonService.java

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
package apelet.tenantadmin.tenant.service;
import apelet.common.core.base.service.IBaseService;
import apelet.common.core.object.CallResult;
import apelet.tenantadmin.tenant.dto.RoleFormButtonDto;
import apelet.tenantadmin.tenant.model.RoleFormButton;
import java.util.List;
import java.util.Map;
/**
* 角色-表单按钮权限配置服务接口
*
* @author chenchuchuan
* @date 2026-07-17
*/
public interface IRoleFormButtonService
extends IBaseService<RoleFormButton, Long> {
/**
* 分页条件查询
*/
List<RoleFormButton> getListByFilter(RoleFormButton filter, String orderBy);
// ========== 核心业务接口 ==========
/**
* 查询按钮权限配置的VO含表单所有按钮 + 勾选状态的合并结果
*
* @param roleId 角色ID
* @param formId 在线表单ID
* @return 包含 formId, roleId, id(配置记录ID), buttonList(含name+checked的列表)
*/
Map<String, Object> getButtonConfigVo(Long roleId, Long formId);
/**
* 批量保存按钮权限配置同一事务内全部成功或全部回滚
*
* @param dtoList 保存入参列表
* @return 保存结果
*/
CallResult batchSaveButtonConfig(List<RoleFormButtonDto> dtoList);
/**
* 保存单条按钮权限配置仅供内部批量方法调用不做事务注解
*
* @param dto 保存入参
* @return 保存结果
*/
CallResult saveButtonConfig(RoleFormButtonDto dto);
/**
* 根据角色ID查询该角色下所有绑定的按钮权限配置
*
* @param roleId 角色ID
* @return 按钮权限配置列表
*/
List<RoleFormButton> listByRoleId(Long roleId);
/**
* 根据角色ID和表单ID查询唯一配置记录
*/
RoleFormButton getByRoleIdAndFormId(Long roleId, Long formId);
/**
* 删除角色下绑定的所有按钮权限配置角色删除时调用
*/
void removeByRoleId(Long roleId);
}

84
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/FormButtonPermissionCheckerImpl.java

@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
package apelet.tenantadmin.tenant.service.impl;
import apelet.common.core.object.TokenData;
import apelet.common.online.service.FormButtonPermissionChecker;
import apelet.tenantadmin.tenant.model.RoleFormButton;
import apelet.tenantadmin.tenant.service.IRoleFormButtonService;
import apelet.tenantadmin.tenant.util.WidgetJsonButtonParser;
import apelet.tenantadmin.upms.dao.SysUserRoleMapper;
import apelet.tenantadmin.upms.model.SysUserRole;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.stream.Collectors;
/**
* 按钮权限检查器实现
* 通过当前用户的所有角色查询 xy_sys_role_form_button
* 判断是否有指定表单-按钮的权限
*
* @author chenchuchuan
* @date 2026-07-17
*/
@Slf4j
@Component
public class FormButtonPermissionCheckerImpl implements FormButtonPermissionChecker {
@Autowired
private SysUserRoleMapper sysUserRoleMapper;
@Autowired
private IRoleFormButtonService roleFormButtonService;
@Override
public boolean hasPermission(Long formId, String buttonName) {
try {
// 1. 获取当前登录用户ID
TokenData tokenData = TokenData.takeFromRequest();
if (tokenData == null) {
log.warn("TokenData 为空,无法校验按钮权限");
return false;
}
Long userId = tokenData.getUserId();
if (userId == null) {
return false;
}
// 2. 获取用户的所有角色
List<SysUserRole> userRoles = sysUserRoleMapper.selectList(
new LambdaQueryWrapper<SysUserRole>()
.eq(SysUserRole::getUserId, userId));
if (userRoles.isEmpty()) {
return false;
}
List<Long> roleIds = userRoles.stream()
.map(SysUserRole::getRoleId)
.collect(Collectors.toList());
// 3. 遍历角色,检查是否有任一角色授权了该表单的该按钮
for (Long roleId : roleIds) {
RoleFormButton config =
roleFormButtonService.getByRoleIdAndFormId(roleId, formId);
if (config != null && config.getButtonConfig() != null) {
List<WidgetJsonButtonParser.ButtonInfo> buttons =
JSON.parseArray(config.getButtonConfig(),
WidgetJsonButtonParser.ButtonInfo.class);
for (WidgetJsonButtonParser.ButtonInfo btn : buttons) {
if (buttonName.equals(btn.getName())
&& Boolean.TRUE.equals(btn.getEnabled())) {
return true;
}
}
}
}
} catch (Exception e) {
log.error("校验按钮权限时发生异常", e);
}
return false;
}
}

182
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/RoleFormButtonServiceImpl.java

@ -0,0 +1,182 @@ @@ -0,0 +1,182 @@
package apelet.tenantadmin.tenant.service.impl;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.common.core.base.service.BaseService;
import apelet.common.core.object.CallResult;
import apelet.common.online.model.OnlineForm;
import apelet.common.online.service.OnlineFormService;
import apelet.common.sequence.wrapper.IdGeneratorWrapper;
import apelet.tenantadmin.tenant.dao.RoleFormButtonMapper;
import apelet.tenantadmin.tenant.dto.RoleFormButtonDto;
import apelet.tenantadmin.tenant.model.RoleFormButton;
import apelet.tenantadmin.tenant.service.IRoleFormButtonService;
import apelet.tenantadmin.tenant.util.WidgetJsonButtonParser;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
/**
* 角色-表单按钮权限配置服务实现
*
* @author chenchuchuan
* @date 2026-07-17
*/
@Service
@Slf4j
public class RoleFormButtonServiceImpl
extends BaseService<RoleFormButton, Long>
implements IRoleFormButtonService {
@Autowired
private RoleFormButtonMapper mapper;
@Autowired
private IdGeneratorWrapper idGenerator;
@Autowired
private OnlineFormService onlineFormService;
@Override
protected BaseDaoMapper<RoleFormButton> mapper() {
return mapper;
}
@Override
public List<RoleFormButton> getListByFilter(
RoleFormButton filter, String orderBy) {
return mapper.getListByFilter(filter, orderBy);
}
// ========== 核心:查询按钮配置VO ==========
@Override
public Map<String, Object> getButtonConfigVo(Long roleId, Long formId) {
Map<String, Object> result = new HashMap<>();
result.put("roleId", roleId);
result.put("formId", formId);
// 1. 获取 widgetJson,提取所有开启的按钮
OnlineForm onlineForm = onlineFormService.getById(formId);
if (onlineForm == null) {
result.put("buttonList", Collections.emptyList());
return result;
}
List<WidgetJsonButtonParser.ButtonInfo> enabledButtons =
WidgetJsonButtonParser.extractEnabledButtons(onlineForm.getWidgetJson());
// 2. 查询已存储的配置
RoleFormButton config = getByRoleIdAndFormId(roleId, formId);
// 3. 解析已勾选的按钮名称集合
Set<String> checkedNames = new HashSet<>();
if (config != null && config.getButtonConfig() != null) {
List<WidgetJsonButtonParser.ButtonInfo> savedButtons =
JSON.parseArray(config.getButtonConfig(),
WidgetJsonButtonParser.ButtonInfo.class);
for (WidgetJsonButtonParser.ButtonInfo btn : savedButtons) {
if (Boolean.TRUE.equals(btn.getEnabled())) {
checkedNames.add(btn.getName());
}
}
}
// 4. 合并:表单所有开启的按钮 + 是否勾选
List<Map<String, Object>> buttonList = new ArrayList<>();
for (WidgetJsonButtonParser.ButtonInfo btn : enabledButtons) {
Map<String, Object> item = new HashMap<>();
item.put("name", btn.getName());
item.put("checked", checkedNames.contains(btn.getName()));
buttonList.add(item);
}
result.put("id", config != null ? config.getId() : null);
result.put("buttonList", buttonList);
return result;
}
// ========== 核心:批量保存按钮配置(事务) ==========
@Override
@Transactional(rollbackFor = Exception.class)
public CallResult batchSaveButtonConfig(List<RoleFormButtonDto> dtoList) {
for (RoleFormButtonDto dto : dtoList) {
CallResult result = this.saveButtonConfig(dto);
if (!result.isSuccess()) {
return result;
}
}
return CallResult.ok();
}
// ========== 核心:保存单条按钮配置(无独立事务,由外层统一管理) ==========
@Override
public CallResult saveButtonConfig(RoleFormButtonDto dto) {
// 1. 必填校验
if (dto.getRoleId() == null) {
return CallResult.error("数据验证失败,角色ID不能为空!");
}
if (dto.getFormId() == null) {
return CallResult.error("数据验证失败,表单ID不能为空!");
}
// 2. 构建 button_config JSON
List<Map<String, Object>> configList = new ArrayList<>();
if (dto.getButtonList() != null) {
for (RoleFormButtonDto.ButtonItem item : dto.getButtonList()) {
Map<String, Object> configItem = new HashMap<>();
configItem.put("name", item.getName());
configItem.put("enabled", Objects.nonNull(item.getChecked()) && item.getChecked());
configList.add(configItem);
}
}
String buttonConfigJson = JSON.toJSONString(configList);
// 3. 查询是否已存在配置(role_id + form_id 唯一)
RoleFormButton existing =
getByRoleIdAndFormId(dto.getRoleId(), dto.getFormId());
if (existing != null) {
// 更新
existing.setButtonConfig(buttonConfigJson);
existing.setUpdateTime(new Date());
this.updateById(existing);
} else {
// 新增
RoleFormButton entity = new RoleFormButton();
entity.setRoleId(dto.getRoleId());
entity.setFormId(dto.getFormId());
entity.setButtonConfig(buttonConfigJson);
entity.setId(idGenerator.nextLongId());
this.save(entity);
}
return CallResult.ok();
}
@Override
public List<RoleFormButton> listByRoleId(Long roleId) {
LambdaQueryWrapper<RoleFormButton> qw = new LambdaQueryWrapper<>();
qw.eq(RoleFormButton::getRoleId, roleId);
return this.list(qw);
}
@Override
public RoleFormButton getByRoleIdAndFormId(Long roleId, Long formId) {
LambdaQueryWrapper<RoleFormButton> qw = new LambdaQueryWrapper<>();
qw.eq(RoleFormButton::getRoleId, roleId)
.eq(RoleFormButton::getFormId, formId);
return this.getOne(qw);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void removeByRoleId(Long roleId) {
LambdaQueryWrapper<RoleFormButton> qw = new LambdaQueryWrapper<>();
qw.eq(RoleFormButton::getRoleId, roleId);
this.remove(qw);
}
}

93
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/util/WidgetJsonButtonParser.java

@ -0,0 +1,93 @@ @@ -0,0 +1,93 @@
package apelet.tenantadmin.tenant.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* widgetJson 按钮解析工具类
* 从在线表单的 widgetJson 中提取所有 operationList 下的按钮
*
* @author chenchuchuan
* @date 2026-07-17
*/
@Slf4j
public class WidgetJsonButtonParser {
/**
* 按钮信息DTO内部类轻量
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class ButtonInfo {
/** 按钮名称 */
private String name;
/** 是否在设计器中开启 */
private Boolean enabled;
}
/**
* widgetJson 中提取所有开启的按钮去重按name
*
* @param widgetJson 在线表单的 widget_json 字段值
* @return 按钮列表只包含 enabled=true 的按钮 name 去重
*/
public static List<ButtonInfo> extractEnabledButtons(String widgetJson) {
List<ButtonInfo> allButtons = extractAllButtons(widgetJson);
List<ButtonInfo> result = new ArrayList<>();
Set<String> seen = new HashSet<>();
for (ButtonInfo btn : allButtons) {
if (Boolean.TRUE.equals(btn.getEnabled()) && seen.add(btn.getName())) {
result.add(btn);
}
}
return result;
}
/**
* widgetJson 中提取所有按钮不去重不过滤
* 仅提取 pc.operationList mobile.operationList 两个顶层数组
* 不递归 tableWidgetwidgetListchildWidgetList 等子节点下的 operationList
*
* @param widgetJson 在线表单的 widget_json 字段值
* @return 全部按钮列表
*/
public static List<ButtonInfo> extractAllButtons(String widgetJson) {
List<ButtonInfo> result = new ArrayList<>();
if (widgetJson == null || widgetJson.isEmpty()) {
return result;
}
try {
JSONObject root = JSON.parseObject(widgetJson);
// 仅取 pc 和 mobile 两端的顶层 operationList
for (String device : new String[]{"pc", "mobile"}) {
JSONObject deviceJson = root.getJSONObject(device);
if (deviceJson == null) continue;
JSONArray operationList = deviceJson.getJSONArray("operationList");
if (operationList != null) {
for (int i = 0; i < operationList.size(); i++) {
JSONObject btn = operationList.getJSONObject(i);
String name = btn.getString("name");
Boolean enabled = btn.getBoolean("enabled");
if (name != null) {
result.add(new ButtonInfo(name, enabled != null ? enabled : false));
}
}
}
}
} catch (Exception e) {
log.error("解析 widgetJson 失败", e);
}
return result;
}
}

17
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/vo/RoleFormButtonVo.java

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
package apelet.tenantadmin.tenant.vo;
import apelet.tenantadmin.tenant.model.RoleFormButton;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 角色-表单按钮权限配置VO对象
*
* @author chenchuchuan
* @date 2026-07-17
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class RoleFormButtonVo extends RoleFormButton {
private static final long serialVersionUID = 1L;
}

20
common/common-online/src/main/java/apelet/common/online/service/FormButtonPermissionChecker.java

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
package apelet.common.online.service;
/**
* 在线表单按钮权限检查器接口
* tenant-admin 模块实现并注册为 Spring Bean
*
* @author chenchuchuan
* @date 2026-07-17
*/
public interface FormButtonPermissionChecker {
/**
* 检查当前用户是否有指定表单上指定按钮的操作权限
*
* @param formId 在线表单ID (zz_online_form.form_id)
* @param buttonName 按钮名称对应 operationList 中的 name 字段
* @return true-有权限false-无权限
*/
boolean hasPermission(Long formId, String buttonName);
}
Loading…
Cancel
Save