fix: 优化导出功能
优化项目导出逻辑
This commit is contained in:
parent
8cfe070b9a
commit
18a5ab367b
@ -1,38 +1,46 @@
|
||||
package io.gisbi.application.appcode.controller;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import io.gisbi.application.appcode.doman.TableData;
|
||||
import io.gisbi.application.appcode.service.DatabaseService;
|
||||
import io.gisbi.application.appcode.utils.ZipUtils;
|
||||
import io.gisbi.application.module.domain.Module;
|
||||
import io.gisbi.application.module.service.IModuleService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/project")
|
||||
public class ProjectExportController {
|
||||
|
||||
|
||||
// 模板 ZIP 文件路径
|
||||
private static final String FIXED_ZIP_PATH = "E:/opt/gisbi2.0/";
|
||||
|
||||
private static final String FIXED_ZIP_NAME = "backend.zip";
|
||||
private static final String FIXED_ZIP_NAME = "stdproject.zip";
|
||||
|
||||
private static final String FIXED_ZIP_FULL_PATH = FIXED_ZIP_PATH + FIXED_ZIP_NAME;
|
||||
|
||||
// 自定义数据库服务类
|
||||
@Autowired
|
||||
private DatabaseService databaseService;
|
||||
|
||||
@Resource
|
||||
private IModuleService moduleService;
|
||||
/**
|
||||
* 接口:导出项目 ZIP 包,插入数据库 SQL 文件后重新打包
|
||||
*/
|
||||
@ -46,9 +54,7 @@ public class ProjectExportController {
|
||||
|
||||
// 创建时间戳和输出 ZIP 名称
|
||||
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
|
||||
String outputZipName = FIXED_ZIP_NAME.replaceFirst("\\..*$", "") +
|
||||
"-with-sql-" + timestamp + ".zip";
|
||||
|
||||
String outputZipName = FIXED_ZIP_NAME.replaceFirst("\\..*$", "") + "_" + timestamp + ".zip";
|
||||
// 定义解压目标路径和最终 ZIP 输出路径
|
||||
// File extractDir = new File(FIXED_ZIP_PATH, "extracted-project");
|
||||
String extractTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
|
||||
@ -75,10 +81,11 @@ public class ProjectExportController {
|
||||
createAndGenerateSqlFile(extractDir, id);
|
||||
|
||||
//TODO 4. 给后端配置文件加上必要的配置
|
||||
modifyBackendConfigFiles(extractDir);
|
||||
// modifyBackendConfigFiles(extractDir);
|
||||
modifyDeepConfigWithYaml(extractDir);
|
||||
|
||||
//TODO 5. 生成前端vue文件
|
||||
generateFrontendVueFiles(extractDir);
|
||||
generateFrontendVueFiles(extractDir, id);
|
||||
|
||||
// 6. 重新打包整个解压后的目录内容
|
||||
ZipUtils.zipDirectoryContents(extractDir, finalZip);
|
||||
@ -96,7 +103,7 @@ public class ProjectExportController {
|
||||
* 创建 db 目录并生成 data.sql 文件
|
||||
*/
|
||||
private void createAndGenerateSqlFile(File extractDir, String id) throws IOException {
|
||||
File dbDir = new File(extractDir, "backend/db");
|
||||
File dbDir = new File(extractDir, "stdproject/backend/db");
|
||||
if (!dbDir.exists() && !dbDir.mkdirs()) {
|
||||
throw new IOException("无法创建 db 目录: " + dbDir.getAbsolutePath());
|
||||
}
|
||||
@ -105,10 +112,74 @@ public class ProjectExportController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改后端配置文件(支持嵌套 YAML 结构)
|
||||
* 修改后端配置文件(支持嵌套 YAML 结构) 通过yaml格式修改
|
||||
*/
|
||||
private static void modifyDeepConfigWithYaml(File extractDir) throws IOException {
|
||||
File configPath = new File(extractDir, "stdproject/backend/src/main/resources/application.yml");
|
||||
if (!configPath.exists()) {
|
||||
throw new FileNotFoundException("配置文件不存在: " + configPath.getAbsolutePath());
|
||||
}
|
||||
|
||||
Yaml yaml = new Yaml();
|
||||
List<Object> allDocuments = new ArrayList<>();
|
||||
// 读取所有文档
|
||||
try (InputStream in = new FileInputStream(configPath)) {
|
||||
for (Object doc : yaml.loadAll(in)) {
|
||||
allDocuments.add(doc);
|
||||
}
|
||||
}
|
||||
|
||||
if (allDocuments.isEmpty()) {
|
||||
throw new IOException("配置文件内容为空");
|
||||
}
|
||||
// 获取第一个文档作为主配置
|
||||
Object firstDoc = allDocuments.getFirst();
|
||||
if (!(firstDoc instanceof Map)) {
|
||||
throw new IOException("第一个文档不是 Map 类型,格式错误");
|
||||
}
|
||||
|
||||
Map<String, Object> root = (Map<String, Object>) firstDoc;
|
||||
|
||||
// 修改 spring.datasource.url 字段
|
||||
if (root.containsKey("spring")) {
|
||||
Map<String, Object> spring = (Map<String, Object>) root.get("spring");
|
||||
if (spring.containsKey("datasource")) {
|
||||
Map<String, Object> datasource = (Map<String, Object>) spring.get("datasource");
|
||||
datasource.put("url", "jdbc:mysql://localhost:3306/newdb");
|
||||
datasource.put("username", "root");
|
||||
datasource.put("password", "123456");
|
||||
}
|
||||
}
|
||||
|
||||
// 修改 server.port 字段
|
||||
if (root.containsKey("server")) {
|
||||
Map<String, Object> server = (Map<String, Object>) root.get("server");
|
||||
server.put("port", 8081);
|
||||
}
|
||||
|
||||
// 更新第一个文档
|
||||
allDocuments.set(0, root);
|
||||
|
||||
// 写回 YAML 文件
|
||||
DumperOptions options = new DumperOptions();
|
||||
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
// 美化输出格式
|
||||
options.setPrettyFlow(true);
|
||||
// 缩进两个空格
|
||||
options.setIndent(2);
|
||||
|
||||
Yaml newYaml = new Yaml(options);
|
||||
|
||||
try (Writer writer = new FileWriter(configPath)) {
|
||||
newYaml.dump(root, writer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改后端配置文件(支持嵌套 YAML 结构)直接根据字符串修改
|
||||
*/
|
||||
private void modifyBackendConfigFiles(File extractDir) throws IOException {
|
||||
File configPath = new File(extractDir, "backend/src/main/resources/application.yml");
|
||||
File configPath = new File(extractDir, "stdproject/backend/src/main/resources/application.yml");
|
||||
if (!configPath.exists()) {
|
||||
throw new FileNotFoundException("配置文件不存在: " + configPath.getAbsolutePath());
|
||||
}
|
||||
@ -147,27 +218,30 @@ public class ProjectExportController {
|
||||
/**
|
||||
* 在前端目录下生成一个 Vue 文件
|
||||
*/
|
||||
private void generateFrontendVueFiles(File extractDir) throws IOException {
|
||||
File vueDir = new File(extractDir, "frontend/src/views/generated");
|
||||
private void generateFrontendVueFiles(File extractDir, String id) throws IOException {
|
||||
File vueDir = new File(extractDir, "stdproject/frontend/src/views/generated");
|
||||
if (!vueDir.exists() && !vueDir.mkdirs()) {
|
||||
throw new IOException("无法创建 Vue 文件目录: " + vueDir.getAbsolutePath());
|
||||
}
|
||||
List<Map<String, Object>> modules =
|
||||
moduleService.listMaps(new LambdaQueryWrapper<Module>().eq(Module::getAppId, id).in(Module::getType,
|
||||
"01", "02").isNotNull(Module::getCanvasStyleData).select(Module::getCanvasStyleData,
|
||||
Module::getName));
|
||||
String fileName = "GeneratedPage";
|
||||
int i = 1;
|
||||
for (Map<String, Object> module : modules) {
|
||||
|
||||
File vueFile = new File(vueDir, "GeneratedPage.vue");
|
||||
|
||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(vueFile))) {
|
||||
writer.write("<template>");
|
||||
writer.newLine();
|
||||
writer.write(" <div>这是自动生成的页面</div>");
|
||||
writer.newLine();
|
||||
writer.write("</template>");
|
||||
writer.newLine();
|
||||
writer.write("<script>");
|
||||
writer.newLine();
|
||||
writer.write("export default { name: 'GeneratedPage' };");
|
||||
writer.newLine();
|
||||
writer.write("</script>");
|
||||
if (ObjectUtil.isEmpty(module.get("canvas_style_data"))) {
|
||||
continue;
|
||||
}
|
||||
String canvasStyleData = module.get("canvas_style_data").toString();
|
||||
File vueFile = new File(vueDir, fileName + i+".vue");
|
||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(vueFile))) {
|
||||
writer.write(canvasStyleData);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -298,6 +298,9 @@ public class DatabaseService {
|
||||
// 对字符串进行转义
|
||||
values.append(escapeSql(s));
|
||||
case null -> values.append("NULL");
|
||||
case Boolean b ->
|
||||
// 将布尔值转换为 0 和 1
|
||||
values.append(b ? 1 : 0);
|
||||
case Number ignored -> values.append(value); // 数字不需要加引号
|
||||
default ->
|
||||
// 其他类型统一转为字符串处理
|
||||
|
@ -2,12 +2,13 @@ package io.gisbi.application.module.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 应用_系统模块
|
||||
|
Loading…
Reference in New Issue
Block a user