Browse Source

feat(tenant-online): 新增租户端表单/报表元数据接口

- TenantOnlFormHeadController:开放查询、保存、删除、tableInfo、
  selectOnlFrom;syncDB/generate/download/defaultData/checkTableName/
  getDir/onlFormSync 统一 404
- TenantOnlCgreportHeadController:开放查询、保存、删除、getData;
  parseSql 等管理端能力 404
feature/2026-10/tenant-multitenant
lml 1 day ago
parent
commit
bf23b3dd58
  1. 188
      common/common-tenant-online/src/main/java/apelet/common/tenant/online/controller/TenantOnlCgreportHeadController.java
  2. 223
      common/common-tenant-online/src/main/java/apelet/common/tenant/online/controller/TenantOnlFormHeadController.java

188
common/common-tenant-online/src/main/java/apelet/common/tenant/online/controller/TenantOnlCgreportHeadController.java

@ -0,0 +1,188 @@
package apelet.common.tenant.online.controller;
import apelet.common.core.annotation.MyRequestBody;
import apelet.common.core.exception.DataNotFoundException;
import apelet.common.core.object.MyOrderParam;
import apelet.common.core.object.MyPageParam;
import apelet.common.core.object.ResponseResult;
import apelet.common.generator.controller.OnlCgreportHeadController;
import apelet.common.generator.dto.OnlCgreportHeadDto;
import apelet.common.tenant.annotation.SwitchTenantCommonDatasource;
import com.alibaba.fastjson.JSONObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 租户端在线报表元数据接口。
*
* <p>只开放报表配置的日常维护(查询、保存、删除、取数),<b>绝对不开放 {@code parseSql}</b>:
* 该接口会用 {@code jdbcTemplate} 直接执行调用方传入的任意 SQL,黑名单可被 union、子查询、
* information_schema 等绕过,租户用户可借此读取同库任意表(含用户密码哈希、其他租户数据)。</p>
*
* <p>注意:Spring MVC 会把父类带 {@code @RequestMapping} 的方法一并注册到子类路径下,
* 仅“不覆写”并不能屏蔽接口。因此这里除了覆写白名单方法外,还显式覆写了所有
* 黑名单方法并统一抛出 {@link DataNotFoundException},由全局异常处理器返回 404。</p>
*
* @author apelet
*/
@SwitchTenantCommonDatasource
@Tag(name = "租户在线报表元数据接口")
@Slf4j
@RestController
@RequestMapping("${common-online.urlPrefix}/tenantOnlCgreportHead")
public class TenantOnlCgreportHeadController extends OnlCgreportHeadController {
/**
* 租户端未开放的接口统一按 404 返回,避免通过状态码区分“不存在”和“无权限”。
*
* @return 404 业务异常。
*/
private DataNotFoundException notOpen() {
return new DataNotFoundException("租户端不开放该接口");
}
/**
* 分页列表查询。租户维度由父类按当前登录租户过滤(PRD FR-4.15)。
*
* @param onlCgreportHeadDto 过滤对象。
* @param orderParam 排序参数。
* @param pageParam 分页参数。
* @return 应答结果对象。
*/
@PostMapping("/page")
@Schema(description = "分页列表查询")
@Override
public ResponseResult<?> page(@MyRequestBody OnlCgreportHeadDto onlCgreportHeadDto,
@MyRequestBody MyOrderParam orderParam,
@MyRequestBody MyPageParam pageParam) {
return super.page(onlCgreportHeadDto, orderParam, pageParam);
}
/**
* 单条查询。
*
* @param id 报表主键Id。
* @return 应答结果对象。
*/
@GetMapping("/getById")
@Schema(description = "单条查询")
@Override
public ResponseResult<?> getById(@RequestParam("id") String id) {
return super.getById(id);
}
/**
* 查询对应 sql 的字段。
*
* @param id 报表主键Id。
* @return 应答结果对象。
*/
@GetMapping("/getFieldsById")
@Schema(description = "查询对应sql的字段")
@Override
public ResponseResult<?> getFieldsById(@RequestParam("id") String id) {
return super.getFieldsById(id);
}
/**
* 查询对应 sql 的参数。
*
* @param id 报表主键Id。
* @return 应答结果对象。
*/
@GetMapping("/getParamsById")
@Schema(description = "查询对应sql的参数")
@Override
public ResponseResult<?> getParamsById(@RequestParam("id") String id) {
return super.getParamsById(id);
}
/**
* 保存报表配置+字段+参数。
*
* @param onlCgreportHeadDto 新增对象。
* @return 应答结果对象。
*/
@PostMapping("/addAll")
@Schema(description = "保存报表配置+字段+参数")
@Override
public ResponseResult<?> addAll(@RequestBody OnlCgreportHeadDto onlCgreportHeadDto) {
return super.addAll(onlCgreportHeadDto);
}
/**
* 编辑报表配置+字段+参数。
*
* @param onlCgreportHeadDto 更新对象。
* @return 应答结果对象。
*/
@PostMapping("/editAll")
@Schema(description = "编辑报表配置+字段+参数")
@Override
public ResponseResult<?> editAll(@RequestBody OnlCgreportHeadDto onlCgreportHeadDto) {
return super.editAll(onlCgreportHeadDto);
}
/**
* 删除报表配置+字段+参数。
*
* @param id 报表主键Id。
* @return 应答结果对象。
*/
@PostMapping("/removeAllById")
@Schema(description = "删除报表配置+字段+参数")
@Override
public ResponseResult<?> removeAllById(@MyRequestBody Long id) {
return super.removeAllById(id);
}
/**
* 根据 code 查询所需的字段信息和搜索字段。
*
* @param code 报表编码。
* @return 应答结果对象。
*/
@GetMapping("/getRpColumns/{code}")
@Schema(description = "根据code查询所需的字段信息和搜索字段-基础版本")
@Override
public ResponseResult<?> getRpColumns(@PathVariable String code) {
return super.getRpColumns(code);
}
/**
* 根据 id 查询具体数据。
*
* @param dto 查询条件。
* @param id 报表主键Id。
* @param pageParam 分页参数。
* @return 应答结果对象。
*/
@PostMapping("/getData")
@Schema(description = "根据id查询具体数据接口-基础版本")
@Override
public ResponseResult<?> getData(@MyRequestBody JSONObject dto,
@MyRequestBody String id,
@MyRequestBody MyPageParam pageParam) {
return super.getData(dto, id, pageParam);
}
/**
* 租户端绝对不开放:会直接用 jdbcTemplate 执行调用方传入的任意 SQL,
* 且 dbKey=easSql 时还会把 SQL 转发到外部 EAS 系统执行(任务清单 #8)。
*/
@GetMapping("/parseSql")
@Schema(description = "租户端不开放")
@Override
public ResponseResult<?> parseSql(@RequestParam(name = "sql") String sql,
@RequestParam(name = "dbKey", required = false) String dbKey) {
throw notOpen();
}
}

223
common/common-tenant-online/src/main/java/apelet/common/tenant/online/controller/TenantOnlFormHeadController.java

@ -0,0 +1,223 @@
package apelet.common.tenant.online.controller;
import apelet.common.core.annotation.MyRequestBody;
import apelet.common.core.exception.DataNotFoundException;
import apelet.common.core.object.MyOrderParam;
import apelet.common.core.object.MyPageParam;
import apelet.common.core.object.ResponseResult;
import apelet.common.generator.controller.OnlFormHeadController;
import apelet.common.generator.dto.OnlFormCodeDto;
import apelet.common.generator.dto.OnlFormHeadDto;
import apelet.common.tenant.annotation.SwitchTenantCommonDatasource;
import com.alibaba.fastjson.JSONObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
/**
* 租户端表单元数据接口。
*
* <p>只开放表单元数据的日常维护(查询、保存、删除、代码生成弹窗、元数据选择),
* 不开放会执行 DDL、生成源码、读取服务器目录、同步外部 EAS 等管理端能力。</p>
*
* <p>注意:Spring MVC 会把父类带 {@code @RequestMapping} 的方法一并注册到子类路径下,
* 仅“不覆写”并不能屏蔽接口。因此这里除了覆写白名单方法外,还显式覆写了所有
* 黑名单方法并统一抛出 {@link DataNotFoundException},由全局异常处理器返回 404。</p>
*
* @author apelet
*/
@SwitchTenantCommonDatasource
@Tag(name = "租户表单元数据接口")
@Slf4j
@RestController
@RequestMapping("${common-online.urlPrefix}/tenantOnlFormHead")
public class TenantOnlFormHeadController extends OnlFormHeadController {
/**
* 租户端未开放的接口统一按 404 返回,避免通过状态码区分“不存在”和“无权限”。
*
* @return 404 业务异常。
*/
private DataNotFoundException notOpen() {
return new DataNotFoundException("租户端不开放该接口");
}
/**
* 分页查询。租户维度由父类按当前登录租户过滤(PRD FR-4.15)。
*
* @param dto 过滤对象。
* @param orderParam 排序参数。
* @param pageParam 分页参数。
* @return 应答结果对象。
*/
@Schema(description = "分页查询")
@PostMapping("/page")
@Override
public ResponseResult<?> page(@MyRequestBody OnlFormHeadDto dto,
@MyRequestBody MyOrderParam orderParam,
@MyRequestBody MyPageParam pageParam) {
return super.page(dto, orderParam, pageParam);
}
/**
* 查询主数据和分录数据。
*
* @param id 主数据主键Id。
* @return 应答结果对象。
*/
@Schema(description = "查询主数据和分录数据")
@GetMapping("/listByHeadId")
@Override
public ResponseResult<?> listByHeadId(@RequestParam Long id) {
return super.listByHeadId(id);
}
/**
* 添加主数据和分录数据。
*
* @param dto 新增对象。
* @return 应答结果对象。
*/
@Schema(description = "添加主数据和分录数据")
@PostMapping("/addAll")
@Override
public ResponseResult<?> addAll(@MyRequestBody OnlFormHeadDto dto) {
return super.addAll(dto);
}
/**
* 编辑主数据和分录数据。
*
* @param dto 更新对象。
* @return 应答结果对象。
*/
@Schema(description = "编辑主数据和分录数据")
@PostMapping("/editAll")
@Override
public ResponseResult<?> editAll(@MyRequestBody OnlFormHeadDto dto) {
return super.editAll(dto);
}
/**
* 删除主数据和分录数据。
*
* @param id 主数据主键Id。
* @return 应答结果对象。
*/
@Schema(description = "删除")
@PostMapping("/removeAllById")
@Override
public ResponseResult<?> removeAllById(@MyRequestBody Long id) {
return super.removeAllById(id);
}
/**
* 代码生成按钮弹出信息。
*
* @param id 主数据主键Id。
* @return 应答结果对象。
*/
@Schema(description = "代码生成按钮弹出信息")
@GetMapping("/tableInfo")
@Override
public ResponseResult<?> tableInfo(@RequestParam Long id) {
return super.tableInfo(id);
}
/**
* 查询对象的所有元数据。
*
* @param name 查询对象name。
* @param type 是否查询字段关联的元数据 1:是 0:否。
* @param isChild 是否查询子表 1:是 0:否。
* @return 应答结果对象。
*/
@Schema(description = "查询对象的所有元数据")
@GetMapping("/selectOnlFrom")
@Override
public ResponseResult<?> selectOnlFrom(@RequestParam String name, @RequestParam String type,
@RequestParam(required = false) Integer isChild) {
return super.selectOnlFrom(name, type, isChild);
}
/**
* 租户端不开放:会执行 DDL。
*/
@Schema(description = "租户端不开放")
@GetMapping("/syncDB")
@Override
public ResponseResult<?> syncDB(@RequestParam("id") Long id, @RequestParam("type") Long type) {
throw notOpen();
}
/**
* 租户端不开放:会生成源码。
*/
@Schema(description = "租户端不开放")
@PostMapping("/generate")
@Override
public ResponseResult<?> generate(@RequestBody OnlFormCodeDto onlFormCodeDto) {
throw notOpen();
}
/**
* 租户端不开放:会读取服务器上的生成文件。
*/
@Schema(description = "租户端不开放")
@PostMapping("/download")
@Override
public void download(@RequestBody JSONObject jsonObject, HttpServletResponse response) {
throw notOpen();
}
/**
* 租户端不开放:返回管理端固定字段定义。
*/
@Schema(description = "租户端不开放")
@GetMapping("/defaultData")
@Override
public ResponseResult<?> defaultData(@RequestParam(required = false) String type,
@RequestParam(required = false) String treeType,
@RequestParam(required = false) String metaType,
@RequestParam(required = false) String metaTable) {
throw notOpen();
}
/**
* 租户端不开放:管理端表名判重。
*/
@Schema(description = "租户端不开放")
@GetMapping("/checkTableName")
@Override
public ResponseResult<?> checkTableName(@RequestParam String tableName) {
throw notOpen();
}
/**
* 租户端不开放:会读取服务器目录。
*/
@Schema(description = "租户端不开放")
@GetMapping("/getDir")
@Override
public ResponseResult<?> getDir(@RequestParam(required = false) String dir) {
throw notOpen();
}
/**
* 租户端不开放:会同步外部 EAS 元数据。
*/
@Schema(description = "租户端不开放")
@GetMapping("/onlFormSync")
@Override
public ResponseResult<?> onlFormSync(@RequestParam("billType") String billType, @RequestParam("id") Long id) {
throw notOpen();
}
}
Loading…
Cancel
Save