1. 代码生成器在生成的时候可以手动选择是否是业务数据类代码(会自动继承基础业务类,合并字段,实现业务接口标记,这个标记会将右上角选择公司作为当前业务数据数据权限进行过滤,办理业务时,如果操作人归属同一个公司的多个部门,会前置校验后弹窗选择归属部门后才能正常办理业务)
2. 文件上传的地方做了一个改动,如果上传文件的 hash 和已存在的附件相同,不会重复上传,会复用相同hash 的附件(要加一个字段,加字段脚本提供两个版本的 patch 脚本 mysql:根目录/sql/mysql/patch.sql dm:根目录/sql/dm/patch.sql )
This commit is contained in:
@@ -34,7 +34,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserNickname;
|
||||
import static cn.iocoder.yudao.module.infra.framework.file.core.utils.FileTypeUtils.writeAttachment;
|
||||
|
||||
@@ -125,21 +124,29 @@ public class CodegenController {
|
||||
|
||||
@Operation(summary = "预览生成代码")
|
||||
@GetMapping("/preview")
|
||||
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
|
||||
@Parameters({
|
||||
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024"),
|
||||
@Parameter(name = "isBusiness", description = "是否业务基类", example = "false")
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('infra:codegen:preview')")
|
||||
public CommonResult<List<CodegenPreviewRespVO>> previewCodegen(@RequestParam("tableId") Long tableId) {
|
||||
Map<String, String> codes = codegenService.generationCodes(tableId);
|
||||
public CommonResult<List<CodegenPreviewRespVO>> previewCodegen(@RequestParam("tableId") Long tableId,
|
||||
@RequestParam(value = "isBusiness", required = false, defaultValue = "false") Boolean isBusiness) {
|
||||
Map<String, String> codes = codegenService.generationCodes(tableId, isBusiness);
|
||||
return success(CodegenConvert.INSTANCE.convert(codes));
|
||||
}
|
||||
|
||||
@Operation(summary = "下载生成代码")
|
||||
@GetMapping("/download")
|
||||
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
|
||||
@Parameters({
|
||||
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024"),
|
||||
@Parameter(name = "isBusiness", description = "是否业务基类", example = "false")
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('infra:codegen:download')")
|
||||
public void downloadCodegen(@RequestParam("tableId") Long tableId,
|
||||
@RequestParam(value = "isBusiness", required = false, defaultValue = "false") Boolean isBusiness,
|
||||
HttpServletResponse response) throws IOException {
|
||||
// 生成代码
|
||||
Map<String, String> codes = codegenService.generationCodes(tableId);
|
||||
// 生成代码,传递 isBusiness
|
||||
Map<String, String> codes = codegenService.generationCodes(tableId, isBusiness);
|
||||
// 构建 zip 包
|
||||
String[] paths = codes.keySet().toArray(new String[0]);
|
||||
ByteArrayInputStream[] ins = codes.values().stream().map(IoUtil::toUtf8Stream).toArray(ByteArrayInputStream[]::new);
|
||||
|
||||
@@ -26,7 +26,7 @@ import lombok.*;
|
||||
public class FileDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号,数据库自增
|
||||
* 编号
|
||||
*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
@@ -57,4 +57,9 @@ public class FileDO extends BaseDO {
|
||||
*/
|
||||
private Integer size;
|
||||
|
||||
/**
|
||||
* 文件哈希值(SHA-256)
|
||||
*/
|
||||
private String hash;
|
||||
|
||||
}
|
||||
|
||||
@@ -23,4 +23,14 @@ public interface FileMapper extends BaseMapperX<FileDO> {
|
||||
.orderByDesc(FileDO::getId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据哈希值查询文件
|
||||
* @param hash 文件哈希值
|
||||
* @return 文件DO,若不存在返回null
|
||||
*/
|
||||
default FileDO selectByHash(String hash) {
|
||||
return selectOne(new LambdaQueryWrapperX<FileDO>()
|
||||
.eq(FileDO::getHash, hash));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -86,6 +86,17 @@ public interface CodegenService {
|
||||
* @param tableId 表编号
|
||||
* @return 生成结果。key 为文件路径,value 为对应的代码内容
|
||||
*/
|
||||
/**
|
||||
* 执行指定表的代码生成,支持业务基类继承
|
||||
* @param tableId 表编号
|
||||
* @param isBusiness 是否业务基类
|
||||
* @return 生成结果
|
||||
*/
|
||||
Map<String, String> generationCodes(Long tableId, Boolean isBusiness);
|
||||
|
||||
/**
|
||||
* 兼容原有接口,默认 isBusiness=false
|
||||
*/
|
||||
Map<String, String> generationCodes(Long tableId);
|
||||
|
||||
/**
|
||||
|
||||
@@ -243,7 +243,10 @@ public class CodegenServiceImpl implements CodegenService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> generationCodes(Long tableId) {
|
||||
/**
|
||||
* 执行指定表的代码生成,支持业务基类继承
|
||||
*/
|
||||
public Map<String, String> generationCodes(Long tableId, Boolean isBusiness) {
|
||||
// 校验是否已经存在
|
||||
CodegenTableDO table = codegenTableMapper.selectById(tableId);
|
||||
if (table == null) {
|
||||
@@ -275,8 +278,16 @@ public class CodegenServiceImpl implements CodegenService {
|
||||
}
|
||||
}
|
||||
|
||||
// 执行生成
|
||||
return codegenEngine.execute(table, columns, subTables, subColumnsList);
|
||||
// 执行生成,传递 isBusiness
|
||||
return codegenEngine.execute(table, columns, subTables, subColumnsList, isBusiness != null && isBusiness);
|
||||
}
|
||||
|
||||
/**
|
||||
* 兼容原有接口,默认 isBusiness=false
|
||||
*/
|
||||
@Override
|
||||
public Map<String, String> generationCodes(Long tableId) {
|
||||
return generationCodes(tableId, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,6 +4,7 @@ import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BusinessBaseDO;
|
||||
import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
|
||||
@@ -67,6 +68,7 @@ public class CodegenBuilder {
|
||||
* {@link cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO} 的字段
|
||||
*/
|
||||
public static final Set<String> BASE_DO_FIELDS = new HashSet<>();
|
||||
public static final Set<String> BUSINESS_BASE_DO_FIELDS = new HashSet<>();
|
||||
/**
|
||||
* 新增操作,不需要传递的字段
|
||||
*/
|
||||
@@ -87,12 +89,18 @@ public class CodegenBuilder {
|
||||
static {
|
||||
Arrays.stream(ReflectUtil.getFields(BaseDO.class)).forEach(field -> BASE_DO_FIELDS.add(field.getName()));
|
||||
BASE_DO_FIELDS.add(TENANT_ID_FIELD);
|
||||
Arrays.stream(ReflectUtil.getFields(BusinessBaseDO.class)).forEach(field -> BUSINESS_BASE_DO_FIELDS.add(field.getName()));
|
||||
BUSINESS_BASE_DO_FIELDS.add(TENANT_ID_FIELD);
|
||||
// 处理 OPERATION 相关的字段
|
||||
CREATE_OPERATION_EXCLUDE_COLUMN.addAll(BASE_DO_FIELDS);
|
||||
UPDATE_OPERATION_EXCLUDE_COLUMN.addAll(BASE_DO_FIELDS);
|
||||
LIST_OPERATION_EXCLUDE_COLUMN.addAll(BASE_DO_FIELDS);
|
||||
LIST_OPERATION_EXCLUDE_COLUMN.remove("createTime"); // 创建时间,还是可能需要传递的
|
||||
LIST_OPERATION_RESULT_EXCLUDE_COLUMN.addAll(BASE_DO_FIELDS);
|
||||
CREATE_OPERATION_EXCLUDE_COLUMN.addAll(BUSINESS_BASE_DO_FIELDS);
|
||||
UPDATE_OPERATION_EXCLUDE_COLUMN.addAll(BUSINESS_BASE_DO_FIELDS);
|
||||
LIST_OPERATION_EXCLUDE_COLUMN.addAll(BUSINESS_BASE_DO_FIELDS);
|
||||
LIST_OPERATION_RESULT_EXCLUDE_COLUMN.addAll(BUSINESS_BASE_DO_FIELDS);
|
||||
LIST_OPERATION_EXCLUDE_COLUMN.remove("createTime"); // 创建时间,还是可能需要传递的
|
||||
LIST_OPERATION_RESULT_EXCLUDE_COLUMN.remove("createTime"); // 创建时间,还是需要返回的
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,7 @@ public interface FileService {
|
||||
/**
|
||||
* 保存文件,并返回文件的访问路径
|
||||
*
|
||||
* <p>会根据文件内容计算哈希值,若已存在相同哈希的文件,则直接复用,不重复上传。</p>
|
||||
* @param content 文件内容
|
||||
* @param name 文件名称,允许空
|
||||
* @param directory 目录,允许空
|
||||
|
||||
@@ -78,13 +78,22 @@ public class FileServiceImpl implements FileService {
|
||||
}
|
||||
|
||||
private FileDO uploadFile(byte[] content, String name, String directory, String type) throws Exception {
|
||||
// 1.1 处理 type 为空的情况
|
||||
// 1.1 计算文件哈希
|
||||
String hash = DigestUtil.sha256Hex(content);
|
||||
|
||||
// 1.2 查找是否已存在相同hash的文件,存在则直接复用
|
||||
FileDO exist = fileMapper.selectByHash(hash);
|
||||
if (exist != null) {
|
||||
return exist;
|
||||
}
|
||||
|
||||
// 1.3 处理 type 为空的情况
|
||||
if (StrUtil.isEmpty(type)) {
|
||||
type = FileTypeUtils.getMineType(content, name);
|
||||
}
|
||||
// 1.2 处理 name 为空的情况
|
||||
// 1.4 处理 name 为空的情况
|
||||
if (StrUtil.isEmpty(name)) {
|
||||
name = DigestUtil.sha256Hex(content);
|
||||
name = hash;
|
||||
}
|
||||
if (StrUtil.isEmpty(FileUtil.extName(name))) {
|
||||
// 如果 name 没有后缀 type,则补充后缀
|
||||
@@ -102,7 +111,8 @@ public class FileServiceImpl implements FileService {
|
||||
String url = client.upload(content, path, type);
|
||||
FileDO entity = new FileDO().setConfigId(client.getId())
|
||||
.setName(name).setPath(path).setUrl(url)
|
||||
.setType(type).setSize(content.length);
|
||||
.setType(type).setSize(content.length)
|
||||
.setHash(hash);
|
||||
|
||||
// 3. 保存到数据库
|
||||
fileMapper.insert(entity);
|
||||
|
||||
@@ -4,6 +4,9 @@ import org.springframework.web.bind.annotation.*;
|
||||
import ${jakartaPackage}.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
#if ($sceneEnum.scene == 1)import org.springframework.security.access.prepost.PreAuthorize;#end
|
||||
#if($isBusiness && $isBusiness == true)
|
||||
import ${basePackage}.framework.business.interceptor.BusinessControllerMarker;
|
||||
#end
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@@ -39,7 +42,12 @@ import ${basePackage}.module.${table.moduleName}.service.${table.businessName}.$
|
||||
##二级的 businessName 暂时不算在 HTTP 路径上,可以根据需要写
|
||||
@RequestMapping("/${table.moduleName}/${simpleClassName_strikeCase}")
|
||||
@Validated
|
||||
## 支持业务基类标记:isBusiness=true 时继承 BusinessControllerMarker
|
||||
#if($isBusiness && $isBusiness == true)
|
||||
public class ${sceneEnum.prefixClass}${table.className}Controller implements BusinessControllerMarker {
|
||||
#else
|
||||
public class ${sceneEnum.prefixClass}${table.className}Controller {
|
||||
#end
|
||||
|
||||
@Resource
|
||||
private ${table.className}Service ${classNameVar}Service;
|
||||
@@ -129,7 +137,7 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
|
||||
#if ($voType == 10)
|
||||
return success(BeanUtils.toBean(list, ${respVOClass}.class));
|
||||
#else
|
||||
return success(list);
|
||||
return success(list);
|
||||
#end
|
||||
}
|
||||
|
||||
@@ -256,15 +264,15 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
|
||||
}
|
||||
#end
|
||||
|
||||
@GetMapping("/${subSimpleClassName_strikeCase}/get")
|
||||
@Operation(summary = "获得${subTable.classComment}")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@GetMapping("/${subSimpleClassName_strikeCase}/get")
|
||||
@Operation(summary = "获得${subTable.classComment}")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
#if ($sceneEnum.scene == 1)
|
||||
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
|
||||
#end
|
||||
public CommonResult<${subTable.className}DO> get${subSimpleClassName}(@RequestParam("id") ${subPrimaryColumn.javaType} id) {
|
||||
return success(${classNameVar}Service.get${subSimpleClassName}(id));
|
||||
}
|
||||
public CommonResult<${subTable.className}DO> get${subSimpleClassName}(@RequestParam("id") ${subPrimaryColumn.javaType} id) {
|
||||
return success(${classNameVar}Service.get${subSimpleClassName}(id));
|
||||
}
|
||||
|
||||
#end
|
||||
#end
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user