Support front draft project preview

This commit is contained in:
王鹏
2026-05-22 15:46:15 +08:00
parent 9ade3e9cb0
commit 1593db9189
7 changed files with 407 additions and 133 deletions

View File

@@ -1,5 +1,8 @@
package com.ruoyi.web.controller.front; package com.ruoyi.web.controller.front;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@@ -8,6 +11,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
@@ -16,7 +20,9 @@ import com.ruoyi.generator.domain.front.dto.DatabaseDesignResponse;
import com.ruoyi.generator.domain.front.dto.FrontProjectCreateRequest; import com.ruoyi.generator.domain.front.dto.FrontProjectCreateRequest;
import com.ruoyi.generator.domain.front.dto.FrontProjectUpdateRequest; import com.ruoyi.generator.domain.front.dto.FrontProjectUpdateRequest;
import com.ruoyi.generator.domain.front.dto.GenerateDatabaseRequest; import com.ruoyi.generator.domain.front.dto.GenerateDatabaseRequest;
import com.ruoyi.generator.domain.front.dto.PreviewFileRequest;
import com.ruoyi.generator.service.front.IAiGenerateService; import com.ruoyi.generator.service.front.IAiGenerateService;
import com.ruoyi.generator.service.front.IFrontProjectPreviewService;
import com.ruoyi.generator.service.front.IFrontProjectService; import com.ruoyi.generator.service.front.IFrontProjectService;
@RestController @RestController
@@ -27,6 +33,8 @@ public class FrontProjectController extends BaseController
private IFrontProjectService frontProjectService; private IFrontProjectService frontProjectService;
@Autowired @Autowired
private IAiGenerateService aiGenerateService; private IAiGenerateService aiGenerateService;
@Autowired
private IFrontProjectPreviewService frontProjectPreviewService;
@PostMapping("/create") @PostMapping("/create")
public AjaxResult create(@RequestBody FrontProjectCreateRequest request) public AjaxResult create(@RequestBody FrontProjectCreateRequest request)
@@ -83,4 +91,40 @@ public class FrontProjectController extends BaseController
Long userId = SecurityUtils.getUserId(); Long userId = SecurityUtils.getUserId();
return success(aiGenerateService.generateDatabase(userId, projectId, request)); return success(aiGenerateService.generateDatabase(userId, projectId, request));
} }
@PostMapping("/{projectId}/preview")
public AjaxResult preview(@PathVariable Long projectId)
{
Long userId = SecurityUtils.getUserId();
frontProjectPreviewService.getStructure(userId, projectId, "backend");
frontProjectPreviewService.getStructure(userId, projectId, "frontend");
frontProjectPreviewService.getStructure(userId, projectId, "admin_frontend");
return toAjax(frontProjectPreviewService.markPreviewReady(userId, projectId));
}
@GetMapping("/{projectId}/structure")
public AjaxResult structure(@PathVariable Long projectId, @RequestParam String templateType)
{
Long userId = SecurityUtils.getUserId();
return success(frontProjectPreviewService.getStructure(userId, projectId, templateType));
}
@GetMapping("/{projectId}/file-content")
public AjaxResult fileContent(@PathVariable Long projectId, PreviewFileRequest request)
{
Long userId = SecurityUtils.getUserId();
return success(frontProjectPreviewService.getFileContent(userId, projectId, request));
}
@GetMapping("/{projectId}/download")
public void download(@PathVariable Long projectId, @RequestParam String templateType, HttpServletResponse response) throws IOException
{
Long userId = SecurityUtils.getUserId();
byte[] data = frontProjectPreviewService.download(userId, projectId, templateType);
response.reset();
response.setHeader("Content-Disposition", "attachment; filename=\"project.zip\"");
response.addHeader("Content-Length", "" + data.length);
response.setContentType("application/octet-stream; charset=UTF-8");
IOUtils.write(data, response.getOutputStream());
}
} }

View File

@@ -2,28 +2,36 @@ package com.ruoyi.generator.service;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.generator.domain.*; import com.ruoyi.generator.domain.GenProject;
import com.ruoyi.generator.domain.GenTable;
import com.ruoyi.generator.domain.GenTableColumn;
import com.ruoyi.generator.domain.SysCodeSnippet;
import com.ruoyi.generator.domain.SysProjectModule;
import com.ruoyi.generator.domain.SysProjectStructure;
import com.ruoyi.generator.domain.SysProjectTemplate;
import com.ruoyi.generator.domain.Template;
import com.ruoyi.generator.domain.TemplateFile;
import com.ruoyi.generator.mapper.GenProjectMapper; import com.ruoyi.generator.mapper.GenProjectMapper;
import com.ruoyi.generator.mapper.GenTableMapper; import com.ruoyi.generator.mapper.GenTableMapper;
import com.ruoyi.generator.util.VelocityInitializer; import com.ruoyi.generator.util.VelocityInitializer;
import com.ruoyi.generator.util.VelocityUtils; import com.ruoyi.generator.util.VelocityUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
/**
* 项目表 服务层实现
*
* @author ruoyi
*/
@Service @Service
public class GenProjectServiceImpl implements IGenProjectService { public class GenProjectServiceImpl implements IGenProjectService {
@Autowired @Autowired
@@ -43,96 +51,60 @@ public class GenProjectServiceImpl implements IGenProjectService {
@Autowired @Autowired
private ISysProjectStructureService sysProjectStructureService; private ISysProjectStructureService sysProjectStructureService;
/**
* 查询项目信息
*
* @param projectId 项目ID
* @return 项目信息
*/
@Override @Override
public GenProject selectGenProjectById(Long projectId) { public GenProject selectGenProjectById(Long projectId) {
return genProjectMapper.selectGenProjectById(projectId); return genProjectMapper.selectGenProjectById(projectId);
} }
/**
* 查询项目列表
*
* @param genProject 项目信息
* @return 项目集合
*/
@Override @Override
public List<GenProject> selectGenProjectList(GenProject genProject) { public List<GenProject> selectGenProjectList(GenProject genProject) {
return genProjectMapper.selectGenProjectList(genProject); return genProjectMapper.selectGenProjectList(genProject);
} }
/**
* 新增项目
*
* @param genProject 项目信息
* @return 结果
*/
@Override @Override
public int insertGenProject(GenProject genProject) { public int insertGenProject(GenProject genProject) {
return genProjectMapper.insertGenProject(genProject); return genProjectMapper.insertGenProject(genProject);
} }
/**
* 修改项目
*
* @param genProject 项目信息
* @return 结果
*/
@Override @Override
public int updateGenProject(GenProject genProject) { public int updateGenProject(GenProject genProject) {
return genProjectMapper.updateGenProject(genProject); return genProjectMapper.updateGenProject(genProject);
} }
/**
* 删除项目对象
*
* @param projectId 项目ID
* @return 结果
*/
@Override @Override
public int deleteGenProjectById(Long projectId) { public int deleteGenProjectById(Long projectId) {
return genProjectMapper.deleteGenProjectById(projectId); return genProjectMapper.deleteGenProjectById(projectId);
} }
/**
* 批量删除项目信息
*
* @param projectIds 需要删除的项目ID
* @return 结果
*/
@Override @Override
public int deleteGenProjectByIds(Long[] projectIds) { public int deleteGenProjectByIds(Long[] projectIds) {
return genProjectMapper.deleteGenProjectByIds(projectIds); return genProjectMapper.deleteGenProjectByIds(projectIds);
} }
/**
* 获取项目结构
*
* @param projectId 项目ID
* @return 项目结构
*/
@Override @Override
public List<Map<String, Object>> getProjectStructure(Long projectId, String type) { public List<Map<String, Object>> getProjectStructure(Long projectId, String type) {
GenProject project = getRequiredProject(projectId); GenProject project = getRequiredProject(projectId);
project.setTables(genTableMapper.selectGenTablesByProjectId(projectId));
List<GenTable> projectTables = genTableMapper.selectGenTablesByProjectId(projectId); return getProjectStructure(project, type);
project.setTables(projectTables); }
List<Map<String, Object>> structure = new ArrayList<>(); @Override
public List<Map<String, Object>> getProjectStructure(GenProject project, String type) {
if (project == null) {
throw new ServiceException("项目信息不能为空");
}
List<GenTable> projectTables = project.getTables();
if (projectTables == null) {
projectTables = new ArrayList<GenTable>();
project.setTables(projectTables);
}
// 获取项目模板 List<Map<String, Object>> structure = new ArrayList<Map<String, Object>>();
SysProjectTemplate projectTemplate = getRequiredProjectTemplate(project, type); SysProjectTemplate projectTemplate = resolveProjectTemplate(project, type);
List<SysProjectStructure> structureNodes = selectStructureNodes(project, projectTemplate);
// 获取模板关联的项目结构节点 Map<Long, SysProjectStructure> sourceNodeMap = new HashMap<Long, SysProjectStructure>();
List<SysProjectStructure> structureNodes = sysProjectStructureService.selectProjectStructureListByModule(project.getProjectId(), projectTemplate.getTemplateId()); Map<String, Map<String, Object>> nodeMap = new LinkedHashMap<String, Map<String, Object>>();
// 构建树形结构
Map<Long, SysProjectStructure> sourceNodeMap = new HashMap<>();
Map<String, Map<String, Object>> nodeMap = new LinkedHashMap<>();
for (SysProjectStructure node : structureNodes) { for (SysProjectStructure node : structureNodes) {
sourceNodeMap.put(node.getNodeId(), node); sourceNodeMap.put(node.getNodeId(), node);
if (isTableScopedNode(node)) { if (isTableScopedNode(node)) {
@@ -146,41 +118,36 @@ public class GenProjectServiceImpl implements IGenProjectService {
} }
} }
// 构建父子关系
for (SysProjectStructure node : structureNodes) { for (SysProjectStructure node : structureNodes) {
if (isTableScopedNode(node)) { if (isTableScopedNode(node)) {
// 处理表特定的节点
for (GenTable table : projectTables) { for (GenTable table : projectTables) {
Map<String, Object> nodeData = nodeMap.get(getNodeKey(node.getNodeId(), table.getTableId())); Map<String, Object> nodeData = nodeMap.get(getNodeKey(node.getNodeId(), table.getTableId()));
addNodeToParent(structure, nodeData, node, nodeMap, sourceNodeMap, table); addNodeToParent(structure, nodeData, node, nodeMap, sourceNodeMap, table);
} }
} else { } else {
// 处理普通节点
Map<String, Object> nodeData = nodeMap.get(getNodeKey(node.getNodeId(), null)); Map<String, Object> nodeData = nodeMap.get(getNodeKey(node.getNodeId(), null));
addNodeToParent(structure, nodeData, node, nodeMap, sourceNodeMap, null); addNodeToParent(structure, nodeData, node, nodeMap, sourceNodeMap, null);
} }
} }
return structure; return structure;
} }
@Override @Override
public byte[] downloadStructure(Long projectId, String type) { public byte[] downloadStructure(Long projectId, String type) {
GenProject project = getRequiredProject(projectId); GenProject project = getRequiredProject(projectId);
project.setTables(genTableMapper.selectGenTablesByProjectId(projectId));
return downloadStructure(project, type);
}
List<GenTable> projectTables = genTableMapper.selectGenTablesByProjectId(projectId); @Override
project.setTables(projectTables); public byte[] downloadStructure(GenProject project, String type) {
if (project == null) {
throw new ServiceException("项目信息不能为空");
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZipOutputStream zip = new ZipOutputStream(outputStream); ZipOutputStream zip = new ZipOutputStream(outputStream);
try { try {
// 获取项目结构 processStructure(getProjectStructure(project, type), zip, project, type);
List<Map<String, Object>> structure = getProjectStructure(projectId, type);
// 递归处理项目结构
processStructure(structure, zip, project, type);
zip.close(); zip.close();
return outputStream.toByteArray(); return outputStream.toByteArray();
} catch (IOException e) { } catch (IOException e) {
@@ -201,19 +168,16 @@ public class GenProjectServiceImpl implements IGenProjectService {
String fullPath = currentPath + name; String fullPath = currentPath + name;
if ("folder".equals(nodeType)) { if ("folder".equals(nodeType)) {
// 创建目录,确保以/结尾
String folderPath = fullPath + "/"; String folderPath = fullPath + "/";
zip.putNextEntry(new ZipEntry(folderPath)); zip.putNextEntry(new ZipEntry(folderPath));
zip.closeEntry(); zip.closeEntry();
// 处理子节点,传递当前完整路径
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<Map<String, Object>> children = (List<Map<String, Object>>) node.get("children"); List<Map<String, Object>> children = (List<Map<String, Object>>) node.get("children");
if (children != null && !children.isEmpty()) { if (children != null && !children.isEmpty()) {
processStructureWithPath(children, zip, project, folderPath, type); processStructureWithPath(children, zip, project, folderPath, type);
} }
} else if ("file".equals(nodeType)) { } else if ("file".equals(nodeType)) {
// 生成文件内容
String content = generateFileContent(project, category, (Long) tableId, type); String content = generateFileContent(project, category, (Long) tableId, type);
if (content != null) { if (content != null) {
zip.putNextEntry(new ZipEntry(fullPath)); zip.putNextEntry(new ZipEntry(fullPath));
@@ -224,33 +188,26 @@ public class GenProjectServiceImpl implements IGenProjectService {
} }
} }
/**
* 预览代码
*
* @param tableId 表编号
* @return 预览数据列表
*/
@Override @Override
public Map<String, String> previewCode(Long projectId, Long tableId, String keyword, String type) public Map<String, String> previewCode(Long projectId, Long tableId, String keyword, String type) {
{
Map<String, String> dataMap = new LinkedHashMap<>();
GenProject project = getRequiredProject(projectId); GenProject project = getRequiredProject(projectId);
List<GenTable> projectTables = genTableMapper.selectGenTablesByProjectId(projectId); project.setTables(genTableMapper.selectGenTablesByProjectId(projectId));
project.setTables(projectTables); return previewCode(project, tableId, keyword, type);
}
SysProjectModule projectModuleFilter = new SysProjectModule(); @Override
projectModuleFilter.setProjectId(project.getProjectId()); public Map<String, String> previewCode(GenProject project, Long tableId, String keyword, String type) {
List<SysProjectModule> modules = sysProjectModuleService.selectSysProjectModuleList(projectModuleFilter); if (project == null) {
throw new ServiceException("项目信息不能为空");
}
Map<String, String> dataMap = new LinkedHashMap<String, String>();
List<SysProjectModule> modules = getProjectModules(project);
VelocityInitializer.initVelocity(); VelocityInitializer.initVelocity();
SysProjectTemplate projectTemplate = resolveProjectTemplate(project, type);
// 获取模板列表
SysProjectTemplate projectTemplate = getRequiredProjectTemplate(project, type);
List<TemplateFile> templateFileList = getRequiredTemplateFiles(projectTemplate.getTemplateId()); List<TemplateFile> templateFileList = getRequiredTemplateFiles(projectTemplate.getTemplateId());
for (TemplateFile templateFile : templateFileList) for (TemplateFile templateFile : templateFileList) {
{ if (matchesTemplateFile(templateFile, keyword)) {
if(matchesTemplateFile(templateFile, keyword)){
// 渲染模板
dataMap.put(templateFile.getFileName(), renderTemplate(project, tableId, modules, templateFile)); dataMap.put(templateFile.getFileName(), renderTemplate(project, tableId, modules, templateFile));
} }
} }
@@ -261,22 +218,16 @@ public class GenProjectServiceImpl implements IGenProjectService {
if (project == null) { if (project == null) {
throw new ServiceException("项目信息不能为空"); throw new ServiceException("项目信息不能为空");
} }
SysProjectModule projectModuleFilter = new SysProjectModule(); List<SysProjectModule> modules = getProjectModules(project);
projectModuleFilter.setProjectId(project.getProjectId());
List<SysProjectModule> modules = sysProjectModuleService.selectSysProjectModuleList(projectModuleFilter);
VelocityInitializer.initVelocity(); VelocityInitializer.initVelocity();
SysProjectTemplate projectTemplate = resolveProjectTemplate(project, type);
// 获取模板列表
SysProjectTemplate projectTemplate = getRequiredProjectTemplate(project, type);
List<TemplateFile> templateFileList = getRequiredTemplateFiles(projectTemplate.getTemplateId()); List<TemplateFile> templateFileList = getRequiredTemplateFiles(projectTemplate.getTemplateId());
for (TemplateFile templateFile : templateFileList) for (TemplateFile templateFile : templateFileList) {
{ if (matchesTemplateFile(templateFile, category)) {
if(matchesTemplateFile(templateFile, category)){
try { try {
return renderTemplate(project, tableId, modules, templateFile); return renderTemplate(project, tableId, modules, templateFile);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
throw new ServiceException("渲染模板失败,表名:" + tableId); throw new ServiceException("渲染模板失败,表名:" + tableId);
} }
} }
@@ -284,6 +235,12 @@ public class GenProjectServiceImpl implements IGenProjectService {
throw new ServiceException("未找到模板文件:" + category); throw new ServiceException("未找到模板文件:" + category);
} }
private List<SysProjectModule> getProjectModules(GenProject project) {
SysProjectModule projectModuleFilter = new SysProjectModule();
projectModuleFilter.setProjectId(project.getProjectId());
return sysProjectModuleService.selectSysProjectModuleList(projectModuleFilter);
}
private GenProject getRequiredProject(Long projectId) { private GenProject getRequiredProject(Long projectId) {
GenProject project = genProjectMapper.selectGenProjectById(projectId); GenProject project = genProjectMapper.selectGenProjectById(projectId);
if (project == null) { if (project == null) {
@@ -292,12 +249,39 @@ public class GenProjectServiceImpl implements IGenProjectService {
return project; return project;
} }
private SysProjectTemplate getRequiredProjectTemplate(GenProject project, String type) { private SysProjectTemplate resolveProjectTemplate(GenProject project, String type) {
SysProjectTemplate projectTemplate = sysProjectTemplateService.selectSysProjectTemplateByProjectAndType(project.getProjectId(), type); SysProjectTemplate projectTemplate = sysProjectTemplateService.selectSysProjectTemplateByProjectAndType(project.getProjectId(), type);
if (projectTemplate == null || projectTemplate.getTemplateId() == null) { if (projectTemplate != null && projectTemplate.getTemplateId() != null) {
throw new ServiceException("项目未配置" + type + "模板"); return projectTemplate;
} }
return projectTemplate;
Template templateFilter = new Template();
templateFilter.setTemplateType(type);
List<Template> templates = templateService.selectTemplateList(templateFilter);
if (StringUtils.isNotEmpty(templates)) {
for (Template template : templates) {
if (template != null && template.getTemplateId() != null && Long.valueOf(0L).equals(template.getTemplateStatus())) {
SysProjectTemplate fallbackTemplate = new SysProjectTemplate();
fallbackTemplate.setProjectId(project.getProjectId());
fallbackTemplate.setTemplateId(template.getTemplateId());
fallbackTemplate.setTemplateType(type);
return fallbackTemplate;
}
}
}
throw new ServiceException("未配置可用模板:" + type);
}
private List<SysProjectStructure> selectStructureNodes(GenProject project, SysProjectTemplate projectTemplate) {
SysProjectTemplate boundProjectTemplate = sysProjectTemplateService.selectSysProjectTemplateByProjectAndType(
project.getProjectId(), projectTemplate.getTemplateType());
if (boundProjectTemplate != null && boundProjectTemplate.getTemplateId() != null) {
return sysProjectStructureService.selectProjectStructureListByModule(project.getProjectId(), projectTemplate.getTemplateId());
}
SysProjectStructure query = new SysProjectStructure();
query.setTemplateId(projectTemplate.getTemplateId());
query.setStatus("0");
return sysProjectStructureService.selectSysProjectStructureList(query);
} }
private List<TemplateFile> getRequiredTemplateFiles(Long templateId) { private List<TemplateFile> getRequiredTemplateFiles(Long templateId) {
@@ -317,14 +301,14 @@ public class GenProjectServiceImpl implements IGenProjectService {
} }
private Map<String, Object> createStructureNodeData(SysProjectStructure node, GenProject project, GenTable table) { private Map<String, Object> createStructureNodeData(SysProjectStructure node, GenProject project, GenTable table) {
Map<String, Object> nodeData = new LinkedHashMap<>(); Map<String, Object> nodeData = new LinkedHashMap<String, Object>();
nodeData.put("id", table == null ? node.getNodeId() : getNodeKey(node.getNodeId(), table.getTableId())); nodeData.put("id", table == null ? node.getNodeId() : getNodeKey(node.getNodeId(), table.getTableId()));
nodeData.put("name", replaceNodeName(node.getNodeName(), project, table)); nodeData.put("name", replaceNodeName(node.getNodeName(), project, table));
nodeData.put("type", node.getNodeType()); nodeData.put("type", node.getNodeType());
nodeData.put("category", node.getCategory()); nodeData.put("category", node.getCategory());
nodeData.put("tableId", table == null ? node.getTableId() : table.getTableId()); nodeData.put("tableId", table == null ? node.getTableId() : table.getTableId());
if ("folder".equals(node.getNodeType())) { if ("folder".equals(node.getNodeType())) {
nodeData.put("children", new ArrayList<>()); nodeData.put("children", new ArrayList<Map<String, Object>>());
} }
return nodeData; return nodeData;
} }
@@ -387,12 +371,10 @@ public class GenProjectServiceImpl implements IGenProjectService {
private VelocityContext prepareVelocityContext(GenProject project, Long tableId, List<SysProjectModule> modules, TemplateFile templateFile) { private VelocityContext prepareVelocityContext(GenProject project, Long tableId, List<SysProjectModule> modules, TemplateFile templateFile) {
if (tableId != null && tableId != -1) { if (tableId != null && tableId != -1) {
GenTable table = getRequiredTable(tableId); GenTable table = getRequiredTable(project, tableId);
table.setModules(modules); table.setModules(modules);
table.setPackageName(project.getPackageName()); table.setPackageName(project.getPackageName());
// 设置主子表信息
setSubTable(table); setSubTable(table);
// 设置主键列信息
setPkColumn(table); setPkColumn(table);
VelocityContext context = VelocityUtils.prepareContext(table); VelocityContext context = VelocityUtils.prepareContext(table);
putSnippetVariables(context, table, modules, templateFile); putSnippetVariables(context, table, modules, templateFile);
@@ -401,7 +383,17 @@ public class GenProjectServiceImpl implements IGenProjectService {
return VelocityUtils.prepareContextProject(project); return VelocityUtils.prepareContextProject(project);
} }
private GenTable getRequiredTable(Long tableId) { private GenTable getRequiredTable(GenProject project, Long tableId) {
if (project != null && StringUtils.isNotEmpty(project.getTables())) {
for (GenTable projectTable : project.getTables()) {
if (projectTable != null && tableId.equals(projectTable.getTableId())) {
if (StringUtils.isEmpty(projectTable.getColumns())) {
throw new ServiceException("业务表未配置字段:" + projectTable.getTableName());
}
return projectTable;
}
}
}
GenTable table = genTableMapper.selectGenTableById(tableId); GenTable table = genTableMapper.selectGenTableById(tableId);
if (table == null) { if (table == null) {
throw new ServiceException("业务表不存在:" + tableId); throw new ServiceException("业务表不存在:" + tableId);
@@ -420,7 +412,7 @@ public class GenProjectServiceImpl implements IGenProjectService {
return; return;
} }
Map<String, StringBuilder> snippetContentMap = new LinkedHashMap<>(); Map<String, StringBuilder> snippetContentMap = new LinkedHashMap<String, StringBuilder>();
for (SysCodeSnippet snippet : codeSnippetList) { for (SysCodeSnippet snippet : codeSnippetList) {
if (StringUtils.isNotEmpty(snippet.getInsertPoint())) { if (StringUtils.isNotEmpty(snippet.getInsertPoint())) {
snippetContentMap.putIfAbsent(snippet.getInsertPoint(), new StringBuilder()); snippetContentMap.putIfAbsent(snippet.getInsertPoint(), new StringBuilder());
@@ -481,11 +473,6 @@ public class GenProjectServiceImpl implements IGenProjectService {
|| matchesTemplateFile(templateFile, snippet.getTemplateFileName()); || matchesTemplateFile(templateFile, snippet.getTemplateFileName());
} }
/**
* 设置主键列信息
*
* @param table 业务表信息
*/
private void setPkColumn(GenTable table) { private void setPkColumn(GenTable table) {
for (GenTableColumn column : table.getColumns()) { for (GenTableColumn column : table.getColumns()) {
if (column.isPk()) { if (column.isPk()) {
@@ -498,11 +485,6 @@ public class GenProjectServiceImpl implements IGenProjectService {
} }
} }
/**
* 设置主子表信息
*
* @param table 业务表信息
*/
public void setSubTable(GenTable table) { public void setSubTable(GenTable table) {
String subTableName = table.getSubTableName(); String subTableName = table.getSubTableName();
if (StringUtils.isNotEmpty(subTableName)) { if (StringUtils.isNotEmpty(subTableName)) {

View File

@@ -69,6 +69,8 @@ public interface IGenProjectService
*/ */
public List<Map<String, Object>> getProjectStructure(Long projectId, String type); public List<Map<String, Object>> getProjectStructure(Long projectId, String type);
public List<Map<String, Object>> getProjectStructure(GenProject project, String type);
/** /**
* 预览代码 * 预览代码
* *
@@ -77,6 +79,8 @@ public interface IGenProjectService
*/ */
public Map<String, String> previewCode(Long projectId, Long tableId, String keyword, String type); public Map<String, String> previewCode(Long projectId, Long tableId, String keyword, String type);
public Map<String, String> previewCode(GenProject project, Long tableId, String keyword, String type);
/** /**
* 下载项目结构 * 下载项目结构
* *
@@ -84,4 +88,6 @@ public interface IGenProjectService
* @return 项目结构ZIP文件字节数组 * @return 项目结构ZIP文件字节数组
*/ */
public byte[] downloadStructure(Long projectId, String type); public byte[] downloadStructure(Long projectId, String type);
}
public byte[] downloadStructure(GenProject project, String type);
}

View File

@@ -0,0 +1,86 @@
package com.ruoyi.generator.service.front;
import com.ruoyi.generator.domain.GenProject;
import com.ruoyi.generator.domain.front.FrontProject;
import com.ruoyi.generator.domain.front.FrontProjectTable;
import com.ruoyi.generator.domain.front.dto.PreviewFileRequest;
import com.ruoyi.generator.mapper.front.FrontProjectColumnMapper;
import com.ruoyi.generator.mapper.front.FrontProjectMapper;
import com.ruoyi.generator.mapper.front.FrontProjectTableMapper;
import com.ruoyi.generator.service.IGenProjectService;
import com.ruoyi.common.exception.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
public class FrontProjectPreviewServiceImpl implements IFrontProjectPreviewService
{
@Autowired
private IFrontProjectService frontProjectService;
@Autowired
private IGenProjectService genProjectService;
@Autowired
private FrontProjectTableMapper frontProjectTableMapper;
@Autowired
private FrontProjectColumnMapper frontProjectColumnMapper;
@Autowired
private FrontProjectMapper frontProjectMapper;
@Override
public List<Map<String, Object>> getStructure(Long userId, Long projectId, String templateType)
{
GenProject genProject = loadGenProject(userId, projectId);
return genProjectService.getProjectStructure(genProject, templateType);
}
@Override
public Map<String, String> getFileContent(Long userId, Long projectId, PreviewFileRequest request)
{
if (request == null)
{
throw new ServiceException("预览文件参数不能为空");
}
GenProject genProject = loadGenProject(userId, projectId);
return genProjectService.previewCode(genProject, request.getTableId(), request.getCategory(), request.getTemplateType());
}
@Override
public byte[] download(Long userId, Long projectId, String templateType)
{
GenProject genProject = loadGenProject(userId, projectId);
return genProjectService.downloadStructure(genProject, templateType);
}
@Override
public int markPreviewReady(Long userId, Long projectId)
{
frontProjectService.getProject(userId, projectId);
FrontProject project = new FrontProject();
project.setProjectId(projectId);
project.setPreviewStatus("1");
return frontProjectMapper.updateFrontProject(project);
}
private GenProject loadGenProject(Long userId, Long projectId)
{
FrontProject frontProject = frontProjectService.getProject(userId, projectId);
if (frontProject.getTables() == null)
{
List<FrontProjectTable> tables = frontProjectTableMapper.selectTablesByProjectId(projectId);
if (tables == null)
{
tables = new ArrayList<FrontProjectTable>();
}
for (FrontProjectTable table : tables)
{
table.setColumns(frontProjectColumnMapper.selectColumnsByTableId(table.getTableId()));
}
frontProject.setTables(tables);
}
return FrontProjectConverter.toGenProject(frontProject);
}
}

View File

@@ -0,0 +1,17 @@
package com.ruoyi.generator.service.front;
import com.ruoyi.generator.domain.front.dto.PreviewFileRequest;
import java.util.List;
import java.util.Map;
public interface IFrontProjectPreviewService
{
public List<Map<String, Object>> getStructure(Long userId, Long projectId, String templateType);
public Map<String, String> getFileContent(Long userId, Long projectId, PreviewFileRequest request);
public byte[] download(Long userId, Long projectId, String templateType);
public int markPreviewReady(Long userId, Long projectId);
}

View File

@@ -7,11 +7,13 @@ import com.ruoyi.generator.domain.SysCodeSnippet;
import com.ruoyi.generator.domain.SysProjectModule; import com.ruoyi.generator.domain.SysProjectModule;
import com.ruoyi.generator.domain.SysProjectStructure; import com.ruoyi.generator.domain.SysProjectStructure;
import com.ruoyi.generator.domain.SysProjectTemplate; import com.ruoyi.generator.domain.SysProjectTemplate;
import com.ruoyi.generator.domain.Template;
import com.ruoyi.generator.domain.TemplateFile; import com.ruoyi.generator.domain.TemplateFile;
import com.ruoyi.generator.mapper.GenProjectMapper; import com.ruoyi.generator.mapper.GenProjectMapper;
import com.ruoyi.generator.mapper.GenTableMapper; import com.ruoyi.generator.mapper.GenTableMapper;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
@@ -25,6 +27,8 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
public class GenProjectServiceImplTest { public class GenProjectServiceImplTest {
private GenProjectServiceImpl service; private GenProjectServiceImpl service;
@@ -34,6 +38,8 @@ public class GenProjectServiceImplTest {
@Mock @Mock
private GenTableMapper genTableMapper; private GenTableMapper genTableMapper;
@Mock @Mock
private ITemplateService templateService;
@Mock
private ITemplateFileService templateFileService; private ITemplateFileService templateFileService;
@Mock @Mock
private ISysCodeSnippetService codeSnippetService; private ISysCodeSnippetService codeSnippetService;
@@ -50,6 +56,7 @@ public class GenProjectServiceImplTest {
service = new GenProjectServiceImpl(); service = new GenProjectServiceImpl();
setField("genProjectMapper", genProjectMapper); setField("genProjectMapper", genProjectMapper);
setField("genTableMapper", genTableMapper); setField("genTableMapper", genTableMapper);
setField("templateService", templateService);
setField("templateFileService", templateFileService); setField("templateFileService", templateFileService);
setField("codeSnippetService", codeSnippetService); setField("codeSnippetService", codeSnippetService);
setField("sysProjectModuleService", sysProjectModuleService); setField("sysProjectModuleService", sysProjectModuleService);
@@ -134,6 +141,38 @@ public class GenProjectServiceImplTest {
assertFalse(content.contains("public void wrong() {}")); assertFalse(content.contains("public void wrong() {}"));
} }
@Test
public void getProjectStructureForDraftProjectUsesFirstActiveTemplateWithoutLoadingProject() {
GenProject project = project();
project.setTables(Arrays.asList(table(11L, "sys_user", "User")));
when(sysProjectTemplateService.selectSysProjectTemplateByProjectAndType(1L, "backend")).thenReturn(null);
when(templateService.selectTemplateList(any(Template.class))).thenReturn(Arrays.asList(
template(99L, 1L),
template(101L, 0L)
));
when(sysProjectStructureService.selectSysProjectStructureList(any(SysProjectStructure.class))).thenReturn(Arrays.asList(
structure(1L, 0L, "{projectName}", "folder", null, null),
structure(2L, 1L, "{ClassName}.java", "file", 0L, "controller.java.vm")
));
List<Map<String, Object>> structure = service.getProjectStructure(project, "backend");
Map<String, Object> root = structure.get(0);
assertEquals("demo-app", root.get("name"));
assertEquals("User.java", child(root, 0).get("name"));
verify(genProjectMapper, never()).selectGenProjectById(any(Long.class));
ArgumentCaptor<Template> templateCaptor = ArgumentCaptor.forClass(Template.class);
verify(templateService).selectTemplateList(templateCaptor.capture());
assertEquals("backend", templateCaptor.getValue().getTemplateType());
ArgumentCaptor<SysProjectStructure> structureCaptor = ArgumentCaptor.forClass(SysProjectStructure.class);
verify(sysProjectStructureService).selectSysProjectStructureList(structureCaptor.capture());
assertEquals(Long.valueOf(101L), structureCaptor.getValue().getTemplateId());
assertEquals("0", structureCaptor.getValue().getStatus());
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Map<String, Object> child(Map<String, Object> node, int index) { private Map<String, Object> child(Map<String, Object> node, int index) {
return ((List<Map<String, Object>>) node.get("children")).get(index); return ((List<Map<String, Object>>) node.get("children")).get(index);
@@ -190,6 +229,14 @@ public class GenProjectServiceImplTest {
return projectTemplate; return projectTemplate;
} }
private Template template(Long templateId, Long templateStatus) {
Template template = new Template();
template.setTemplateId(templateId);
template.setTemplateType("backend");
template.setTemplateStatus(templateStatus);
return template;
}
private SysProjectModule projectModule(Long moduleId) { private SysProjectModule projectModule(Long moduleId) {
SysProjectModule module = new SysProjectModule(); SysProjectModule module = new SysProjectModule();
module.setProjectId(1L); module.setProjectId(1L);

View File

@@ -0,0 +1,92 @@
package com.ruoyi.generator.service.front;
import com.ruoyi.generator.domain.GenProject;
import com.ruoyi.generator.domain.front.FrontProject;
import com.ruoyi.generator.domain.front.FrontProjectColumn;
import com.ruoyi.generator.domain.front.FrontProjectTable;
import com.ruoyi.generator.service.IGenProjectService;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
public class FrontProjectPreviewServiceImplTest
{
private FrontProjectPreviewServiceImpl previewService;
@Mock
private IFrontProjectService frontProjectService;
@Mock
private IGenProjectService genProjectService;
@Before
public void setUp() throws Exception
{
MockitoAnnotations.initMocks(this);
previewService = new FrontProjectPreviewServiceImpl();
setField("frontProjectService", frontProjectService);
setField("genProjectService", genProjectService);
}
@Test
public void returnsStructureForDraftProject()
{
when(frontProjectService.getProject(100L, 200L)).thenReturn(frontProjectWithOneTable());
when(genProjectService.getProjectStructure(any(GenProject.class), eq("backend")))
.thenReturn(Collections.singletonList(Collections.singletonMap("label", "backend")));
List<Map<String, Object>> structure = previewService.getStructure(100L, 200L, "backend");
assertEquals("backend", structure.get(0).get("label"));
}
private void setField(String name, Object value) throws Exception
{
Field field = FrontProjectPreviewServiceImpl.class.getDeclaredField(name);
field.setAccessible(true);
field.set(previewService, value);
}
private FrontProject frontProjectWithOneTable()
{
FrontProject project = new FrontProject();
project.setProjectId(200L);
project.setProjectName("Demo");
project.setProjectFileName("demo");
project.setPackageName("com.example.demo");
project.setTables(Arrays.asList(table()));
return project;
}
private FrontProjectTable table()
{
FrontProjectTable table = new FrontProjectTable();
table.setTableId(300L);
table.setTableName("sys_user");
table.setClassName("User");
table.setColumns(Arrays.asList(column()));
return table;
}
private FrontProjectColumn column()
{
FrontProjectColumn column = new FrontProjectColumn();
column.setTableId(300L);
column.setColumnName("id");
column.setJavaType("Long");
column.setJavaField("id");
column.setIsPk("1");
return column;
}
}