diff --git a/front/src/views/generate/GenerateConfig/index.vue b/front/src/views/generate/GenerateConfig/index.vue
index aea8b71888d41246a3cac0b39c92a510a14ad5cf..79903009cb3f7bde7f0d74cde071242ddcaac221 100644
--- a/front/src/views/generate/GenerateConfig/index.vue
+++ b/front/src/views/generate/GenerateConfig/index.vue
@@ -37,6 +37,10 @@
+
+
+
+
@@ -188,9 +192,12 @@
-
+
+
+
+
+
+
下载全部
+ >下载全部 导出到项目路径
+
+
@@ -56,6 +68,7 @@ import JSZip from 'jszip'
import { saveAs } from 'file-saver'
import { codemirror } from 'vue-codemirror'
import 'codemirror/theme/neat.css'
+import {configs} from "eslint-plugin-vue";
require('codemirror/mode/javascript/javascript')
require('codemirror/mode/clike/clike')
require('codemirror/mode/htmlembedded/htmlembedded')
@@ -72,6 +85,11 @@ const mode_map = {
'xml': 'application/xml'
}
export default {
+ computed: {
+ configs() {
+ return configs
+ }
+ },
components: { codemirror },
data() {
return {
@@ -80,6 +98,7 @@ export default {
datasourceConfigId: '',
tableNames: [],
templateConfigIdList: [],
+ outPath: "",
packageName: ''
},
treeData: [],
@@ -217,7 +236,27 @@ export default {
// see FileSaver.js
saveAs(content, `code-${new Date().getTime()}.zip`)
})
+ },
+ exportToProject() {
+ if (!this.clientParam.outPath) {
+ this.tip('项目路径为空', 'error')
+ return
+ }
+ if (this.loading) {
+ return
+ }
+ this.loading = true
+ this.post(`/generate/export`, {
+ ...this.clientParam,
+
+ }, function(resp) {
+ this.tip('导出成功', 'success')
+ this.loading = false
+ })
+
}
+
+
}
}
diff --git a/gen/src/main/java/com/gitee/gen/common/GeneratorParam.java b/gen/src/main/java/com/gitee/gen/common/GeneratorParam.java
index f2b924181d847af9f5f8792ccaf120d4347e563b..bd2cccefac0446f92f4291964ee1b58f10fef77b 100644
--- a/gen/src/main/java/com/gitee/gen/common/GeneratorParam.java
+++ b/gen/src/main/java/com/gitee/gen/common/GeneratorParam.java
@@ -13,6 +13,7 @@ public class GeneratorParam {
private List templateConfigIdList;
private String packageName;
+ private String outPath;
private String delPrefix;
@@ -20,6 +21,14 @@ public class GeneratorParam {
private String charset = "UTF-8";
+ public String getOutPath() {
+ return outPath;
+ }
+
+ public void setOutPath(String outPath) {
+ this.outPath = outPath;
+ }
+
public int getDatasourceConfigId() {
return datasourceConfigId;
}
@@ -83,6 +92,7 @@ public class GeneratorParam {
", tableNames=" + tableNames +
", templateConfigIdList=" + templateConfigIdList +
", packageName='" + packageName + '\'' +
+ ", projectRoot='" + outPath + '\'' +
", delPrefix='" + delPrefix + '\'' +
", author='" + author + '\'' +
", charset='" + charset + '\'' +
diff --git a/gen/src/main/java/com/gitee/gen/common/MemCache.java b/gen/src/main/java/com/gitee/gen/common/MemCache.java
new file mode 100644
index 0000000000000000000000000000000000000000..7e4b0560eeefa11bbd3d4a4a5a59076b6bceb631
--- /dev/null
+++ b/gen/src/main/java/com/gitee/gen/common/MemCache.java
@@ -0,0 +1,84 @@
+package com.gitee.gen.common;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * 简易内存缓存:LRU + 10 分钟过期(最后一次访问)
+ */
+public class MemCache {
+
+ private final int maxSize;
+ private final long expireMillis;
+
+ /* 存数据 + 时间戳 */
+ private static class ValueWrapper {
+ V value;
+ long lastAccess;
+
+ ValueWrapper(V v) {
+ this.value = v;
+ this.lastAccess = System.currentTimeMillis();
+ }
+ }
+
+ private final Map> map;
+ private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+
+ public MemCache(int maxSize, long expireMinutes) {
+ this.maxSize = maxSize;
+ this.expireMillis = expireMinutes * 60 * 1000;
+
+ // LinkedHashMap 实现 LRU
+ this.map = new LinkedHashMap>(16, 0.75f, true) {
+ @Override
+ protected boolean removeEldestEntry(Map.Entry> eldest) {
+ return size() > MemCache.this.maxSize;
+ }
+ };
+ }
+
+ public void put(K key, V value) {
+ lock.writeLock().lock();
+ try {
+ map.put(key, new ValueWrapper<>(value));
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ public V get(K key) {
+ lock.readLock().lock();
+ try {
+ ValueWrapper w = map.get(key);
+ if (w == null) return null;
+ // 过期判断
+ if (System.currentTimeMillis() - w.lastAccess > expireMillis) {
+ lock.readLock().unlock();
+ lock.writeLock().lock();
+ try {
+ map.remove(key);
+ } finally {
+ lock.writeLock().unlock();
+ }
+ return null;
+ }
+ // 更新时间戳
+ w.lastAccess = System.currentTimeMillis();
+ return w.value;
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ public V remove(K key) {
+ lock.writeLock().lock();
+ try {
+ ValueWrapper w = map.remove(key);
+ return w == null ? null : w.value;
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+}
\ No newline at end of file
diff --git a/gen/src/main/java/com/gitee/gen/config/AppRouterInterceptor.java b/gen/src/main/java/com/gitee/gen/config/AppRouterInterceptor.java
index 0d929776eb5758f36502a9c56b44946710f1c8cf..ca27cbfab2382147e18779ce497eac1c1edd29f2 100644
--- a/gen/src/main/java/com/gitee/gen/config/AppRouterInterceptor.java
+++ b/gen/src/main/java/com/gitee/gen/config/AppRouterInterceptor.java
@@ -19,8 +19,10 @@ public class AppRouterInterceptor implements RouterInterceptor {
ctx.render(Action.err("资源不存在"));
}
} catch (ValidatorException e) {
+ e.printStackTrace();
ctx.render(Action.err(e.getMessage())); //e.getResult().getDescription()
} catch (Throwable e) {
+ e.printStackTrace();
ctx.render(Action.err(e.getMessage()));
}
}
diff --git a/gen/src/main/java/com/gitee/gen/controller/GeneratorController.java b/gen/src/main/java/com/gitee/gen/controller/GeneratorController.java
index f92d73d2b6d06f402600d48a16851c257430bedb..f8fdaaf37013f3b4b08e3b56bdb7ef4649d73231 100644
--- a/gen/src/main/java/com/gitee/gen/controller/GeneratorController.java
+++ b/gen/src/main/java/com/gitee/gen/controller/GeneratorController.java
@@ -4,13 +4,21 @@ import com.gitee.gen.common.Action;
import com.gitee.gen.common.GeneratorParam;
import com.gitee.gen.common.Result;
import com.gitee.gen.entity.DatasourceConfig;
+import com.gitee.gen.gen.CodeFile;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.service.DatasourceConfigService;
import com.gitee.gen.service.GeneratorService;
+import com.gitee.gen.common.MemCache;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.Mapping;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
/**
* @author tanghc
*/
@@ -24,6 +32,12 @@ public class GeneratorController {
@Inject
private GeneratorService generatorService;
+
+private final MemCache> codeCache =
+ new MemCache<>(100, 10); // 最大 100 条,10 分钟过期
+
+
+
/**
* 生成代码
*
@@ -35,7 +49,45 @@ public class GeneratorController {
int datasourceConfigId = generatorParam.getDatasourceConfigId();
DatasourceConfig datasourceConfig = datasourceConfigService.getById(datasourceConfigId);
GeneratorConfig generatorConfig = GeneratorConfig.build(datasourceConfig);
- return Action.ok(generatorService.generate(generatorParam, generatorConfig));
+
+ List generate = generatorService.generate(generatorParam, generatorConfig);
+
+ String key = generatorParam.getDatasourceConfigId() + "_" + String.join(",", generatorParam.getTableNames());
+ codeCache.put(key, generate);
+ return Action.ok(generate);
+ }
+ /**
+ * 导出文件到指定路径
+ *
+ * @param generatorParam 生成参数
+ * @return 返回代码内容
+ */
+ @Mapping("/export")
+ public Result export(GeneratorParam generatorParam) throws IOException {
+ System.out.println(generatorParam);
+ String key = generatorParam.getDatasourceConfigId() + "_" + String.join(",", generatorParam.getTableNames());
+ System.out.println(key);
+ List generate = null;
+ List cacheFiles = codeCache.get(key);
+ if (cacheFiles == null) {
+ // 缓存中没有找到代码
+ System.out.println("缓存中没有找到代码");
+ int datasourceConfigId = generatorParam.getDatasourceConfigId();
+ DatasourceConfig datasourceConfig = datasourceConfigService.getById(datasourceConfigId);
+ GeneratorConfig generatorConfig = GeneratorConfig.build(datasourceConfig);
+ generate = generatorService.generate(generatorParam, generatorConfig);
+ }else {
+ generate = cacheFiles;
+ }
+
+
+ System.out.println("导出代码文件:" + generate);
+ String result = generatorService.export(generate, generatorParam);
+
+ System.out.println(result);
+ return Action.ok(result);
+
}
+
}
diff --git a/gen/src/main/java/com/gitee/gen/entity/DatasourceConfig.java b/gen/src/main/java/com/gitee/gen/entity/DatasourceConfig.java
index 42e87c58c5e715c690f2daf741e3fe4dae1ffd6f..2719d613ce9ebcaf410d00da71a282170d7ed2c5 100644
--- a/gen/src/main/java/com/gitee/gen/entity/DatasourceConfig.java
+++ b/gen/src/main/java/com/gitee/gen/entity/DatasourceConfig.java
@@ -41,6 +41,17 @@ public class DatasourceConfig {
/** 数据库分组名称 */
private String dbGroupName;
+ /** 导出路径 */
+ private String outPath;
+
+ public String getOutPath() {
+ return outPath;
+ }
+
+ public void setOutPath(String outPath) {
+ this.outPath = outPath;
+ }
+
public Integer getId() {
return id;
}
diff --git a/gen/src/main/java/com/gitee/gen/service/GeneratorService.java b/gen/src/main/java/com/gitee/gen/service/GeneratorService.java
index f5912aafe341447dbc8a0f9876a2a2a03a7aa40c..7e9db9f51b1c17ab5c2a8ff53c98bab54af69ca9 100644
--- a/gen/src/main/java/com/gitee/gen/service/GeneratorService.java
+++ b/gen/src/main/java/com/gitee/gen/service/GeneratorService.java
@@ -13,9 +13,17 @@ import com.gitee.gen.util.FormatUtil;
import com.gitee.gen.util.VelocityUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.velocity.VelocityContext;
+import org.apache.velocity.texen.util.FileUtil;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -169,4 +177,45 @@ public class GeneratorService {
return VelocityUtil.generate(context, template);
}
+ public String export(List generate, GeneratorParam generatorParam) throws IOException {
+
+ Path outPath = Paths.get(generatorParam.getOutPath());
+ // 判断导出路径是否存在
+ if (!Files.exists(outPath)) {
+ try {
+ Files.createDirectories(outPath);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return "创建导出路径失败";
+ }
+ }
+ System.out.println("导出路径:" + outPath);
+ String packagePath = generatorParam.getPackageName().replace(".", File.separator);
+ Path packageDir = outPath.resolve(packagePath);
+ System.out.println("导出包路径:" + packageDir);
+ boolean success = true;
+
+ for (CodeFile codeFile : generate) {
+ try {
+ Path folder = packageDir.resolve(codeFile.getFolder());
+ Files.createDirectories(folder);
+ System.out.println("导出文件夹路径:" + folder);
+ // 文件:folder + fileName
+ Path target = folder.resolve(codeFile.getFileName());
+ System.out.println("导出文件路径:" + target);
+ Files.write(target, codeFile.getContent().getBytes(StandardCharsets.UTF_8),
+ StandardOpenOption.CREATE,
+ StandardOpenOption.TRUNCATE_EXISTING);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.out.println("导出文件失败:" + codeFile.getFileName());
+ success = false;
+ }
+ }
+ if (success) {
+ return "导出成功";
+ }
+ return "导出失败";
+ }
+
}
diff --git a/gen/src/main/java/com/gitee/gen/util/TemplateMetaUtils.java b/gen/src/main/java/com/gitee/gen/util/TemplateMetaUtils.java
index 7dc53848417a3e20223b14c4b74445da717ea9fb..feba0d4f7ba8089f16802c93f7a63b57a3c9fcf1 100644
--- a/gen/src/main/java/com/gitee/gen/util/TemplateMetaUtils.java
+++ b/gen/src/main/java/com/gitee/gen/util/TemplateMetaUtils.java
@@ -31,11 +31,46 @@ public final class TemplateMetaUtils {
* 解析元数据信息
*/
public static Map parseMetaRow(String row) {
+ char[] charArray = row.toCharArray();
+
Map data = new HashMap<>();
- String[] paris = row.split("\\s*,\\s*");
- for (String item : paris) {
- String[] kv = item.split("=");
- data.put(kv[0].trim(), kv.length == 1 ? null : kv[1].trim());
+
+ StringBuilder kvBuilder = new StringBuilder();
+ // 剩余未闭合表达式数量
+ int leftExpr = 0;
+ for (int i = 0, len = charArray.length, end = len - 1; i < len; i++) {
+ char c = charArray[i];
+ boolean kvEnd = false;
+ if (i == end) {
+ kvBuilder.append(c);
+ kvEnd = true;
+ } else if (',' == c && leftExpr == 0) {
+ kvEnd = true;
+ }
+
+ if (kvEnd) {
+ String[] kv = kvBuilder.toString().trim().split("=");
+ data.put(kv[0].trim(), kv.length == 1 ? null : kv[1].trim());
+ kvBuilder = new StringBuilder();
+ continue;
+ }
+
+ kvBuilder.append(c);
+ switch (c) {
+ case '{':
+ case '(':
+ leftExpr++;
+ break;
+ case '}':
+ case ')':
+ leftExpr--;
+ break;
+ default:
+ break;
+ }
+ }
+ if (leftExpr > 0) {
+ throw new RuntimeException("读取元数据失败,有" + leftExpr + "个表达式未闭合");
}
return data;
}
diff --git a/gen/src/main/resources/gen_init.db b/gen/src/main/resources/gen_init.db
index 795f8f18ac3765db61be902861cd92d74cccccf6..ebfbffcc186c948cfcfa5f59d976d7b8b6aaa9c3 100644
Binary files a/gen/src/main/resources/gen_init.db and b/gen/src/main/resources/gen_init.db differ
diff --git a/gen/src/main/resources/mybatis/DatasourceConfigMapper.xml b/gen/src/main/resources/mybatis/DatasourceConfigMapper.xml
index 0e96a7f3d35eef4e961d9b86fabd0b493ddf8d95..45bb3146fd0f33c08660a92fd529c8fad32bd435 100644
--- a/gen/src/main/resources/mybatis/DatasourceConfigMapper.xml
+++ b/gen/src/main/resources/mybatis/DatasourceConfigMapper.xml
@@ -18,6 +18,7 @@
+
@@ -38,6 +39,7 @@
, t.group_id
, t.author
, t.db_group_name
+ , t.out_path
@@ -77,6 +79,7 @@
group_id,
author,
db_group_name,
+ out_path,
#{dbType},
@@ -94,6 +97,7 @@
#{groupId},
#{author},
#{dbGroupName},
+ #{out_path},
@@ -148,6 +152,8 @@
db_group_name,
+
+ out_path,
@@ -195,6 +201,8 @@
#{dbGroupName},
+
+ #{outPath},
@@ -218,6 +226,7 @@
group_id=#{groupId},
author=#{author},
db_group_name=#{dbGroupName},
+ out_path=#{outPath},
WHERE id = #{id}
@@ -271,6 +280,8 @@
db_group_name=#{dbGroupName},
+
+ out_path=#{outPath},
WHERE id = #{id}