refactor: 添加菜单feign客户端,提供代码生成新增菜单

This commit is contained in:
Ray.Hao 2024-09-07 19:52:33 +08:00
parent 02f2c8e640
commit daec9f8542
17 changed files with 126 additions and 38 deletions

View File

@ -13,7 +13,7 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
* @since 0.0.1 * @since 0.0.1
*/ */
@SpringBootApplication @SpringBootApplication
@EnableDiscoveryClient() @EnableDiscoveryClient
@EnableFeignClients(basePackageClasses = {SkuFeignClient.class}) @EnableFeignClients(basePackageClasses = {SkuFeignClient.class})
public class MemberApplication { public class MemberApplication {
public static void main(String[] args) { public static void main(String[] args) {

View File

@ -72,6 +72,11 @@
<artifactId>velocity-engine-core</artifactId> <artifactId>velocity-engine-core</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.youlai</groupId>
<artifactId>system-api</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -1,15 +1,20 @@
package com.youlai.codegen; package com.youlai.codegen;
import com.youlai.system.api.MenuFeignClient;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
/** /**
* 系统服务启动类 * 代码生成器启动类
* *
* @author Ray * @author Ray
* @since 0.0.1 * @since 4.0.0
*/ */
@SpringBootApplication @SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackageClasses = {MenuFeignClient.class})
public class CodegenApplication { public class CodegenApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(CodegenApplication.class, args); SpringApplication.run(CodegenApplication.class, args);

View File

@ -7,7 +7,7 @@ import com.youlai.common.result.Result;
import com.youlai.codegen.config.CodegenProperties; import com.youlai.codegen.config.CodegenProperties;
import com.youlai.codegen.model.form.GenConfigForm; import com.youlai.codegen.model.form.GenConfigForm;
import com.youlai.codegen.model.query.TablePageQuery; import com.youlai.codegen.model.query.TablePageQuery;
import com.youlai.codegen.model.vo.CodePreviewVO; import com.youlai.codegen.model.vo.CodegenPreviewVO;
import com.youlai.codegen.model.vo.TablePageVO; import com.youlai.codegen.model.vo.TablePageVO;
import com.youlai.codegen.service.GenConfigService; import com.youlai.codegen.service.GenConfigService;
import com.youlai.codegen.service.CodegenService; import com.youlai.codegen.service.CodegenService;
@ -91,14 +91,14 @@ public class CodegenController {
@Operation(summary = "获取预览生成代码") @Operation(summary = "获取预览生成代码")
@GetMapping("/{tableName}/preview") @GetMapping("/{tableName}/preview")
public Result<List<CodePreviewVO>> getCodePreviewData(@PathVariable String tableName) { public Result<List<CodegenPreviewVO>> getCodePreviewData(@PathVariable String tableName) {
List<CodePreviewVO> list = codegenService.getCodePreviewData(tableName); List<CodegenPreviewVO> list = codegenService.getCodePreviewData(tableName);
return Result.success(list); return Result.success(list);
} }
@Operation(summary = "下载代码") @Operation(summary = "下载代码")
@GetMapping("/{tableName}/download") @GetMapping("/{tableName}/download")
public void downloadZip(HttpServletResponse response, @PathVariable String tableName) throws IOException { public void downloadZip(HttpServletResponse response, @PathVariable String tableName) {
String[] tableNames = tableName.split(","); String[] tableNames = tableName.split(",");
byte[] data = codegenService.downloadCode(tableNames); byte[] data = codegenService.downloadCode(tableNames);

View File

@ -3,6 +3,7 @@ package com.youlai.codegen.converter;
import com.youlai.codegen.model.entity.GenConfig; import com.youlai.codegen.model.entity.GenConfig;
import com.youlai.codegen.model.entity.GenFieldConfig; import com.youlai.codegen.model.entity.GenFieldConfig;
import com.youlai.codegen.model.form.GenConfigForm; import com.youlai.codegen.model.form.GenConfigForm;
import com.youlai.system.dto.CodegenMenuDTO;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
@ -36,4 +37,8 @@ public interface CodegenConverter {
GenFieldConfig toGenFieldConfig(GenConfigForm.FieldConfig fieldConfig); GenFieldConfig toGenFieldConfig(GenConfigForm.FieldConfig fieldConfig);
@Mapping(source = "parentMenuId", target = "parentMenuId")
CodegenMenuDTO toCodegenMenuDTO(Long parentMenuId, GenConfig genConfig);
} }

View File

@ -5,7 +5,7 @@ import lombok.Data;
@Schema(description = "代码生成代码预览VO") @Schema(description = "代码生成代码预览VO")
@Data @Data
public class CodePreviewVO { public class CodegenPreviewVO {
@Schema(description = "生成文件路径") @Schema(description = "生成文件路径")
private String path; private String path;

View File

@ -2,7 +2,7 @@ package com.youlai.codegen.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.codegen.model.query.TablePageQuery; import com.youlai.codegen.model.query.TablePageQuery;
import com.youlai.codegen.model.vo.CodePreviewVO; import com.youlai.codegen.model.vo.CodegenPreviewVO;
import com.youlai.codegen.model.vo.TablePageVO; import com.youlai.codegen.model.vo.TablePageVO;
import java.util.List; import java.util.List;
@ -29,7 +29,7 @@ public interface CodegenService {
* @param tableName 表名 * @param tableName 表名
* @return 包含代码预览信息的列表 * @return 包含代码预览信息的列表
*/ */
List<CodePreviewVO> getCodePreviewData(String tableName); List<CodegenPreviewVO> getCodePreviewData(String tableName);
/** /**
* 下载代码 * 下载代码

View File

@ -12,7 +12,6 @@ import com.youlai.codegen.model.form.GenConfigForm;
*/ */
public interface GenConfigService extends IService<GenConfig> { public interface GenConfigService extends IService<GenConfig> {
/** /**
* 获取代码生成配置 * 获取代码生成配置
* *

View File

@ -17,7 +17,7 @@ import com.youlai.codegen.enums.JavaTypeEnum;
import com.youlai.codegen.model.entity.GenConfig; import com.youlai.codegen.model.entity.GenConfig;
import com.youlai.codegen.model.entity.GenFieldConfig; import com.youlai.codegen.model.entity.GenFieldConfig;
import com.youlai.codegen.model.query.TablePageQuery; import com.youlai.codegen.model.query.TablePageQuery;
import com.youlai.codegen.model.vo.CodePreviewVO; import com.youlai.codegen.model.vo.CodegenPreviewVO;
import com.youlai.codegen.model.vo.TablePageVO; import com.youlai.codegen.model.vo.TablePageVO;
import com.youlai.codegen.service.DatabaseService; import com.youlai.codegen.service.DatabaseService;
import com.youlai.codegen.service.GenConfigService; import com.youlai.codegen.service.GenConfigService;
@ -93,9 +93,9 @@ public class CodegenServiceImpl implements CodegenService {
* @return 预览数据 * @return 预览数据
*/ */
@Override @Override
public List<CodePreviewVO> getCodePreviewData(String tableName) { public List<CodegenPreviewVO> getCodePreviewData(String tableName) {
List<CodePreviewVO> list = new ArrayList<>(); List<CodegenPreviewVO> list = new ArrayList<>();
GenConfig genConfig = genConfigService.getOne(new LambdaQueryWrapper<GenConfig>() GenConfig genConfig = genConfigService.getOne(new LambdaQueryWrapper<GenConfig>()
.eq(GenConfig::getTableName, tableName) .eq(GenConfig::getTableName, tableName)
@ -116,7 +116,7 @@ public class CodegenServiceImpl implements CodegenService {
// 遍历模板配置 // 遍历模板配置
Map<String, CodegenProperties.TemplateConfig> templateConfigs = codegenProperties.getTemplateConfigs(); Map<String, CodegenProperties.TemplateConfig> templateConfigs = codegenProperties.getTemplateConfigs();
for (Map.Entry<String, CodegenProperties.TemplateConfig> templateConfigEntry : templateConfigs.entrySet()) { for (Map.Entry<String, CodegenProperties.TemplateConfig> templateConfigEntry : templateConfigs.entrySet()) {
CodePreviewVO previewVO = new CodePreviewVO(); CodegenPreviewVO previewVO = new CodegenPreviewVO();
CodegenProperties.TemplateConfig templateConfig = templateConfigEntry.getValue(); CodegenProperties.TemplateConfig templateConfig = templateConfigEntry.getValue();
@ -308,9 +308,9 @@ public class CodegenServiceImpl implements CodegenService {
* @param zip 压缩文件输出流 * @param zip 压缩文件输出流
*/ */
private void generateAndZipCode(String tableName, ZipOutputStream zip) { private void generateAndZipCode(String tableName, ZipOutputStream zip) {
List<CodePreviewVO> codePreviewList = getCodePreviewData(tableName); List<CodegenPreviewVO> codePreviewList = getCodePreviewData(tableName);
for (CodePreviewVO codePreview : codePreviewList) { for (CodegenPreviewVO codePreview : codePreviewList) {
String fileName = codePreview.getFileName(); String fileName = codePreview.getFileName();
String content = codePreview.getContent(); String content = codePreview.getContent();
String path = codePreview.getPath(); String path = codePreview.getPath();

View File

@ -21,6 +21,8 @@ import com.youlai.codegen.model.entity.GenFieldConfig;
import com.youlai.codegen.model.form.GenConfigForm; import com.youlai.codegen.model.form.GenConfigForm;
import com.youlai.codegen.service.GenConfigService; import com.youlai.codegen.service.GenConfigService;
import com.youlai.codegen.service.GenFieldConfigService; import com.youlai.codegen.service.GenFieldConfigService;
import com.youlai.system.api.MenuFeignClient;
import com.youlai.system.dto.CodegenMenuDTO;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -41,7 +43,7 @@ public class GenConfigServiceImpl extends ServiceImpl<GenConfigMapper, GenConfig
private final CodegenProperties codegenProperties; private final CodegenProperties codegenProperties;
private final GenFieldConfigService genFieldConfigService; private final GenFieldConfigService genFieldConfigService;
private final CodegenConverter codegenConverter; private final CodegenConverter codegenConverter;
/* private final MenuService menuService;*/ private final MenuFeignClient menuFeignClient;
@Value("${spring.profiles.active}") @Value("${spring.profiles.active}")
private String springProfilesActive; private String springProfilesActive;
@ -174,10 +176,11 @@ public class GenConfigServiceImpl extends ServiceImpl<GenConfigMapper, GenConfig
GenConfig genConfig = codegenConverter.toGenConfig(formData); GenConfig genConfig = codegenConverter.toGenConfig(formData);
this.saveOrUpdate(genConfig); this.saveOrUpdate(genConfig);
// 如果选择上级菜单 // 如果选择上级菜单且当前环境不是生产环境则新增菜单
Long parentMenuId = formData.getParentMenuId(); Long parentMenuId = formData.getParentMenuId();
if (parentMenuId != null && EnvEnum.DEV.getValue().equals(springProfilesActive) ) { if (parentMenuId != null && EnvEnum.PROD.getValue().equals(springProfilesActive)) {
// menuService.saveMenu(parentMenuId, genConfig); CodegenMenuDTO codegenMenuDTO = codegenConverter.toCodegenMenuDTO(parentMenuId, genConfig);
menuFeignClient.addMenuForCodegen(codegenMenuDTO);
} }
List<GenFieldConfig> genFieldConfigs = codegenConverter.toGenFieldConfig(formData.getFieldConfigs()); List<GenFieldConfig> genFieldConfigs = codegenConverter.toGenFieldConfig(formData.getFieldConfigs());

View File

@ -3,12 +3,12 @@ server:
spring: spring:
application: application:
name: youlai-generator name: youlai-codegen
profiles: profiles:
active: dev active: dev
# 代码生成器配置 # 代码生成器配置
generator: codegen:
# 下载代码文件名称 # 下载代码文件名称
downloadFileName: youlai-mall-code.zip downloadFileName: youlai-mall-code.zip
# 后端项目名称 # 后端项目名称

View File

@ -12,8 +12,8 @@ import lombok.Getter;
@Getter @Getter
public enum EnvEnum implements IBaseEnum<String> { public enum EnvEnum implements IBaseEnum<String> {
DEV("dev", "开发"), DEV("dev", "开发环境"),
PROD("prod", "生产"); PROD("prod", "生产环境");
private final String value; private final String value;

View File

@ -0,0 +1,14 @@
package com.youlai.system.api;
import com.youlai.common.core.config.FeignDecoderConfig;
import com.youlai.system.dto.CodegenMenuDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(value = "youlai-system", contextId = "menu", configuration = {FeignDecoderConfig.class})
public interface MenuFeignClient {
@PostMapping("/api/v1/menus/codegen")
void addMenuForCodegen( @RequestBody CodegenMenuDTO data);
}

View File

@ -7,7 +7,7 @@ import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(value = "youlai-system", fallback = UserFeignFallbackClient.class, configuration = {FeignDecoderConfig.class}) @FeignClient(value = "youlai-system", contextId = "user", fallback = UserFeignFallbackClient.class, configuration = {FeignDecoderConfig.class})
public interface UserFeignClient { public interface UserFeignClient {
@GetMapping("/api/v1/users/{username}/authInfo") @GetMapping("/api/v1/users/{username}/authInfo")

View File

@ -113,16 +113,14 @@ public class MenuController {
return Result.judge(result); return Result.judge(result);
} }
/** /**
* 代码生成器生成代码新增菜单 * 代码生成器生成代码新增菜单
*/ */
@PostMapping("/codegen") @PostMapping("/codegen")
public Result<Void> createCodegenMenu( public Result<Void> addMenuForCodegen(
@RequestBody @Valid CodegenMenuDTO data @RequestBody @Valid CodegenMenuDTO data
) { ) {
boolean result = menuService.addMenuForCodegen(data);
boolean result = menuService.createCodegenMenu(data);
return Result.judge(result); return Result.judge(result);
} }

View File

@ -64,5 +64,5 @@ public interface MenuService extends IService<Menu> {
/** /**
* 保存生成代码菜单 * 保存生成代码菜单
*/ */
boolean createCodegenMenu(@Valid CodegenMenuDTO data); boolean addMenuForCodegen(@Valid CodegenMenuDTO data);
} }

View File

@ -338,15 +338,74 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements Me
} }
/** /**
* 保存生成代码菜单 * 代码生成时添加菜单
* *
* @param data * @param data {@link CodegenMenuDTO} 代码生成菜单数据传输对象
* @return * @return 是否成功
*/ */
@Override @Override
public boolean createCodegenMenu(CodegenMenuDTO data) { public boolean addMenuForCodegen(CodegenMenuDTO data) {
return false; Long parentMenuId = data.getParentMenuId();
Menu parentMenu = this.getById(parentMenuId);
Assert.notNull(parentMenu, "上级菜单不存在");
String entityName =data.getEntityName();
long count = this.count(new LambdaQueryWrapper<Menu>().eq(Menu::getRouteName, entityName));
if (count > 0) {
throw new RuntimeException("菜单已存在");
}
// 业务名称 e.g. 用户管理
String businessName = data.getBusinessName();
// 模块名称 e.g. system
String moduleName = data.getModuleName();
// 获取父级菜单子菜单最带的排序
Menu maxSortMenu = this.getOne(new LambdaQueryWrapper<Menu>().eq(Menu::getParentId, parentMenuId)
.orderByDesc(Menu::getSort)
.last("limit 1")
);
int sort = 1;
if (maxSortMenu != null) {
sort = maxSortMenu.getSort() + 1;
}
Menu menu = new Menu();
menu.setParentId(parentMenuId);
menu.setName(businessName);
menu.setRouteName(entityName);
menu.setRoutePath(StrUtil.toSymbolCase(entityName, '-'));
menu.setComponent(data.getModuleName() + "/" + StrUtil.toSymbolCase(entityName, '-') + "/index");
menu.setType(MenuTypeEnum.MENU);
menu.setSort(sort);
menu.setVisible(1);
boolean result = this.save(menu);
if (result) {
// 生成treePath
String treePath = generateMenuTreePath(parentMenuId);
menu.setTreePath(treePath);
this.updateById(menu);
// 生成CURD按钮权限
String permPrefix = data.getModuleName() + ":" + StrUtil.lowerFirst(entityName) + ":";
String[] actions = {"查询", "新增", "编辑", "删除"};
String[] perms = {"query", "add", "edit", "delete"};
for (int i = 0; i < actions.length; i++) {
Menu button = new Menu();
button.setParentId(menu.getId());
button.setType(MenuTypeEnum.BUTTON);
button.setName(actions[i]);
button.setPerm(permPrefix + perms[i]);
button.setSort(i + 1);
this.save(button);
// 生成 treepath
button.setTreePath(treePath + "," + button.getId());
this.updateById(button);
}
}
return result;
} }
} }