Skip to content

Commit cef0488

Browse files
committed
古法编程·非遗传承
1 parent d6a09de commit cef0488

7 files changed

Lines changed: 189 additions & 17 deletions

File tree

‎README.md‎

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
![image](https://img.shields.io/badge/SpringBoot3-%E2%98%85%E2%98%85%E2%98%85%E2%98%85%E2%98%85-blue.svg)
77
![image](https://img.shields.io/badge/Freemarker-%E2%98%85%E2%98%85%E2%98%85%E2%98%85%E2%98%85-blue.svg)
88
![image](https://img.shields.io/badge/CodeGenerator-%E2%98%85%E2%98%85%E2%98%85%E2%98%85%E2%98%85-blue.svg)
9+
[![非遗](https://img.shields.io/badge/%E9%9D%9E%E9%81%97-%E5%8F%A4%E6%B3%95%E7%BC%96%E7%A8%8B%E4%BC%A0%E6%89%BF%E8%80%85-8B4513.svg)](#description)
910
[![Java CI with Maven](https://github.com/moshowgame/SpringBootCodeGenerator/actions/workflows/maven.yml/badge.svg)](https://github.com/moshowgame/SpringBootCodeGenerator/actions/workflows/maven.yml)
1011

1112
# Author
@@ -34,11 +35,20 @@
3435
> 📦 **One-click ZIP download** — package all generated code into a structured ZIP in one click\
3536
> 📦 **一键 ZIP 打包下载** — 按模板分组自动归档,告别逐个文件复制
3637
37-
> 🙏 Thanks for your continued support! BeJSON once peaked at 1.5K daily PV 👀, and now maintains a steady flow of around 600 visits — plus 2K+ GitHub Stars ✨. Your feedback remains our greatest motivation to keep improving!
38-
> ❤️ 感谢大家一直以来的支持!BeJSON 曾创下日均访问量 1.5K 👀 的高峰,目前稳定在约 600 左右,GitHub Star 数也已突破 2K ✨。你们的反馈始终是我们不断前进的最大动力!
39-
40-
> 🌈 Wishing everyone balance, health, and success — may your code be bug-free and your coffee strong ☕\
41-
> 💬 祝大家工作顺利,生活平衡,身体健康,步步高升,代码无 bug,咖啡够劲!
38+
> 🏺 In the age of AI vibe coding, every line of these templates is still handcrafted — traditional code craft, certified intangible cultural heritage\
39+
> 🏺 AI vibe coding 时代,本项目的模板依然坚持手搓:开启「🏺 古法印章」,生成的每份代码都会带上一枚非遗传承手作印章,ZIP 包内附《手工代码认证书》——致敬每一位古法编程非遗传承者!
40+
41+
> ### 🐺 写在 AI 时代
42+
>
43+
> 大狼狗代码生成器诞生于 2018 年,彼时 AI 写代码还是科幻。数万开发者使用过它,数千颗 Star 见证了它的成长。
44+
>
45+
> 如今 AI 浪潮滚滚而来,我们选择不追逐风口,而是回归本质:
46+
>
47+
> - **工具的价值**,在于服务人,而非替代人;
48+
> - **代码的价值**,在于解决问题,而非堆砌行数;
49+
> - **开发者的价值**,在于思考与判断,而非手速与复制。
50+
>
51+
> 感谢每一位使用过大狼狗的朋友。愿你在 AI 时代,既有工具的效率,也有匠人的定力。🙏
4252
4353
> 📬 Feel free to submit issues, share useful templates, or contribute your brilliant ideas via PR\
4454
> 🤝 欢迎提交问题、分享常用模板,或将你的灵感通过 PR 实现!
@@ -309,7 +319,7 @@ ResultVo.error(message);
309319

310320
| 更新日期 | 更新内容 |
311321
| :--------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
312-
| 2026.09.09 | 🎨 前端全面重构为 jQuery3 + Bootstrap 5.3 + CodeMirror 5:全新 `newui3` 现代化界面,`data-bs-theme` 原生深/浅色模式(CodeMirror 双主题跟随),输出区按模板类型动态切换语法高亮(Java/XML/SQL/JSON/JS);新增 `app.js` 独立命名空间 `CodeGenApp`(与旧版 main.js 零冲突),补齐本地 mode 文件(sql/clike/xml/javascript);新增🏺古法印章开关(isHeritage,致敬古法编程非遗传承者);模板选择区改为组内联布局,`template.json` 支持 `tier` 字段分级(main 常驻 / legacy 折叠),折叠与选中状态 localStorage 记忆;修复 JDK23+ 下 Lombok 注解处理不生效的编译问题; |
322+
| 2026.09.09 | 🎨 前端全面重构为 jQuery3 + Bootstrap 5.3 + CodeMirror 5:全新 `newui3` 现代化界面,`data-bs-theme` 原生深/浅色模式(CodeMirror 双主题跟随),输出区按模板类型动态切换语法高亮(Java/XML/SQL/JSON/JS);新增 `app.js` 独立命名空间 `CodeGenApp`(与旧版 main.js 零冲突),补齐本地 mode 文件(sql/clike/xml/javascript);新增🏺古法印章开关(isHeritage,致敬古法编程非遗传承者);模板选择区改为组内联布局,`template.json` 支持 `tier` 字段分级(main 常驻 / legacy 折叠),折叠与选中状态 localStorage 记忆;修复 JDK23+ 下 Lombok 注解处理不生效的编译问题;🏺非遗传承后端落地:`HeritageUtil` 按内容嗅探+后缀适配注释语法盖章(Java/JS/QVS 用 `//`,SQL 用 `--`,YAML 用 `#`,XML/Vue/HTML 在声明后插 `<!-- -->`,JSON 不盖章),ZIP 首条目附《手工代码认证书》;修正 `template.json` 中 `swagger-ui`/`beanutil`/`qliksense` 三个模板 fileName 后缀与实际内容类型不符的问题,并修复 ZIP 包误将 `tableName` 字段打成伪文件的 bug; |
313323
| 2026.06.02 | 📦 新增"一键 ZIP 打包下载"功能:在生成按钮旁新增独立下载按钮,按模板 group 自动分目录打包成 ZIP;<br>支持 `template.json` 中 `fileName` 字段(含 `${className}` 占位符),智能推断文件后缀; |
314324
| 2025.12.09 | 优化Mybatis和Mybatis-Plus模板 |
315325
| 2025.12.08 | 引入单元测试和JaCoCo测试覆盖率,优化代码覆盖率 [UNIT\_TEST\_DOCUMENT.md](UNIT_TEST_DOCUMENT.md) |

‎src/main/java/com/softdev/system/generator/controller/CodeGenController.java‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import com.softdev.system.generator.entity.vo.ResultVo;
77
import com.softdev.system.generator.service.CodeGenService;
88
import com.softdev.system.generator.service.ZipService;
9+
import com.softdev.system.generator.util.HeritageUtil;
10+
import com.softdev.system.generator.util.MapUtil;
911
import lombok.RequiredArgsConstructor;
1012
import lombok.extern.slf4j.Slf4j;
1113
import org.springframework.http.HttpHeaders;
@@ -66,7 +68,7 @@ public ResponseEntity<byte[]> generateCodeAsZip(@RequestBody ParamInfo paramInfo
6668
result.getFileNameTemplates(),
6769
result.getGroupByTemplate(),
6870
zipName,
69-
buildContext(result)
71+
buildContext(result, paramInfo.getOptions())
7072
);
7173

7274
String encoded = URLEncoder.encode(zipName + ".zip", StandardCharsets.UTF_8)
@@ -95,12 +97,14 @@ private Map<String, Object> prepareOptions(ParamInfo paramInfo) throws Exception
9597
}
9698

9799
/**
98-
* 构造 ZIP 解析占位符所需的上下文
100+
* 构造 ZIP 解析占位符所需的上下文(含非遗传承印章开关与作者)
99101
*/
100-
private Map<String, Object> buildContext(CodeGenResult result) {
102+
private Map<String, Object> buildContext(CodeGenResult result, Map<String, Object> options) {
101103
Map<String, Object> ctx = new HashMap<>();
102104
ctx.put("className", result.getClassName() == null ? "" : result.getClassName());
103105
ctx.put("tableName", result.getTableName() == null ? "" : result.getTableName());
106+
ctx.put("isHeritage", HeritageUtil.isEnabled(options));
107+
ctx.put("author", MapUtil.getString(options, "authorName"));
104108
return ctx;
105109
}
106110
}

‎src/main/java/com/softdev/system/generator/service/impl/CodeGenServiceImpl.java‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.softdev.system.generator.service.parser.JsonParserService;
1313
import com.softdev.system.generator.service.parser.SqlParserService;
1414
import com.softdev.system.generator.util.FreemarkerUtil;
15+
import com.softdev.system.generator.util.HeritageUtil;
1516
import com.softdev.system.generator.util.MapUtil;
1617
import lombok.RequiredArgsConstructor;
1718
import lombok.extern.slf4j.Slf4j;
@@ -70,6 +71,7 @@ public CodeGenResult getResultByParams(Map<String, Object> params) throws Except
7071

7172
generatedCode.put("tableName", MapUtil.getString(params, "tableName"));
7273

74+
boolean heritage = HeritageUtil.isEnabled(params);
7375
JSONArray parentTemplates = templateService.getAllTemplates();
7476
for (int i = 0; i < parentTemplates.size(); i++) {
7577
JSONObject parentTemplateObj = parentTemplates.getJSONObject(i);
@@ -81,6 +83,9 @@ public CodeGenResult getResultByParams(Map<String, Object> params) throws Except
8183
String templateName = childTemplate.getString("name");
8284
String templatePath = group + "/" + templateName + ".ftl";
8385
String generatedText = FreemarkerUtil.processString(templatePath, params);
86+
if (heritage) {
87+
generatedText = HeritageUtil.stamp(childTemplate.getString("fileName"), generatedText);
88+
}
8489
generatedCode.put(templateName, generatedText);
8590
fileNameTemplates.put(templateName, childTemplate.getString("fileName"));
8691
groupByTemplate.put(templateName, group);

‎src/main/java/com/softdev/system/generator/service/impl/ZipServiceImpl.java‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.softdev.system.generator.service.impl;
22

33
import com.softdev.system.generator.service.ZipService;
4+
import com.softdev.system.generator.util.HeritageUtil;
45
import com.softdev.system.generator.util.ZipFileNameResolver;
56
import lombok.extern.slf4j.Slf4j;
67
import org.springframework.stereotype.Service;
@@ -9,8 +10,10 @@
910
import java.io.IOException;
1011
import java.nio.charset.StandardCharsets;
1112
import java.util.HashSet;
13+
import java.util.List;
1214
import java.util.Map;
1315
import java.util.Set;
16+
import java.util.stream.Collectors;
1417
import java.util.zip.ZipEntry;
1518
import java.util.zip.ZipOutputStream;
1619

@@ -40,10 +43,21 @@ public byte[] buildZip(Map<String, String> generatedCode,
4043
Set<String> usedPaths = new HashSet<>();
4144
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
4245
zos.setLevel(java.util.zip.Deflater.BEST_SPEED);
46+
// 🏺 非遗传承:手工代码认证书作为 ZIP 首个条目
47+
if (HeritageUtil.isEnabled(context)) {
48+
List<String> templateNames = generatedCode.keySet().stream()
49+
.filter(name -> !"tableName".equals(name))
50+
.collect(Collectors.toList());
51+
String certificate = HeritageUtil.buildCertificate(
52+
stringOf(context, "className"), stringOf(context, "tableName"),
53+
stringOf(context, "author"), templateNames);
54+
writeEntry(zos, "手工代码认证书.txt", certificate);
55+
}
4356
for (Map.Entry<String, String> entry : generatedCode.entrySet()) {
4457
String templateName = entry.getKey();
4558
String content = entry.getValue();
46-
if (content == null) {
59+
// tableName 是返回给前端的结构化字段,不是代码文件
60+
if (content == null || "tableName".equals(templateName)) {
4761
continue;
4862
}
4963
String fileNameTpl = fileNameTemplates == null ? null : fileNameTemplates.get(templateName);
@@ -67,6 +81,14 @@ private void writeEntry(ZipOutputStream zos, String entryPath, String content) t
6781
zos.closeEntry();
6882
}
6983

84+
private String stringOf(Map<String, Object> context, String key) {
85+
if (context == null || key == null) {
86+
return "";
87+
}
88+
Object value = context.get(key);
89+
return value == null ? "" : value.toString();
90+
}
91+
7092
/**
7193
* 构造 entry 路径;遇到重名时加 _1 / _2 ...
7294
*/
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package com.softdev.system.generator.util;
2+
3+
import java.time.LocalDateTime;
4+
import java.time.format.DateTimeFormatter;
5+
import java.util.List;
6+
import java.util.Map;
7+
8+
/**
9+
* 🏺 非遗传承工具:为生成的代码加盖手作印章,并生成手工代码认证书
10+
* <p>
11+
* 在 AI vibe coding 的时代,每一行模板都坚持手搓,致敬古法编程非遗传承者。
12+
*
13+
* @author zhengkai.blog.csdn.net
14+
*/
15+
public final class HeritageUtil {
16+
17+
private static final String LINE_1 = "🏺 古法编程·非遗传承 | Traditional Code Craft since 2018";
18+
private static final String LINE_2 = "本代码由手作模板工艺生成,非 AI vibe coding 之作 | Handcrafted, not AI-generated.";
19+
20+
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
21+
22+
private HeritageUtil() {
23+
}
24+
25+
/**
26+
* isHeritage 是否启用;未显式关闭(false)时默认开启
27+
*/
28+
public static boolean isEnabled(Map<String, Object> params) {
29+
Object flag = params == null ? null : params.get("isHeritage");
30+
return flag == null || Boolean.TRUE.equals(flag) || "true".equalsIgnoreCase(String.valueOf(flag));
31+
}
32+
33+
/**
34+
* 在文件头部盖手作印章;JSON 等不支持注释的文件类型原样返回
35+
*
36+
* @param fileName 模板配置中的目标文件名(用于推断注释语法,可能不准,仅作兜底)
37+
* @param content 生成的代码文本
38+
*/
39+
public static String stamp(String fileName, String content) {
40+
if (content == null || content.isEmpty()) {
41+
return content;
42+
}
43+
// 内容嗅探优先:模板配置的 fileName 可能与实际内容类型不符(如 mapper 标为 .java 实为 XML)
44+
String trimmed = content.trim();
45+
if (trimmed.startsWith("<")) {
46+
return stampAsXmlComment(content);
47+
}
48+
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
49+
return content;
50+
}
51+
switch (extensionOf(fileName)) {
52+
case "java":
53+
case "jjs":
54+
case "js":
55+
case "qvs":
56+
return "// " + LINE_1 + "\n// " + LINE_2 + "\n" + content;
57+
case "sql":
58+
return "-- " + LINE_1 + "\n-- " + LINE_2 + "\n" + content;
59+
case "yml":
60+
case "yaml":
61+
case "properties":
62+
case "txt":
63+
return "# " + LINE_1 + "\n# " + LINE_2 + "\n" + content;
64+
case "xml":
65+
case "html":
66+
case "vue":
67+
case "md":
68+
return stampAsXmlComment(content);
69+
default:
70+
return content;
71+
}
72+
}
73+
74+
/**
75+
* 手工代码认证书(ZIP 彩蛋)
76+
*/
77+
public static String buildCertificate(String className, String tableName, String author, List<String> templateNames) {
78+
StringBuilder sb = new StringBuilder();
79+
sb.append("🏺 手工代码认证书\n");
80+
sb.append("CERTIFICATE OF HANDCRAFTED CODE\n");
81+
sb.append("================================================================\n\n");
82+
sb.append("兹证明\n\n");
83+
sb.append(" ").append(safe(className)).append("(表 ").append(safe(tableName)).append(")的 ")
84+
.append(templateNames == null ? 0 : templateNames.size()).append(" 份代码\n");
85+
sb.append(" 均由「古法编程·非遗传承」工艺生成。\n\n");
86+
sb.append("模板清单:\n");
87+
if (templateNames != null) {
88+
for (String name : templateNames) {
89+
sb.append(" · ").append(name).append('\n');
90+
}
91+
}
92+
sb.append('\n');
93+
sb.append("工匠:").append(author == null || author.trim().isEmpty() ? "Anonymous" : author.trim()).append('\n');
94+
sb.append("时间:").append(LocalDateTime.now().format(TIME_FORMATTER)).append('\n');
95+
sb.append("工艺:Freemarker 手作模板 + 自研/JSqlParser 双解析引擎\n\n");
96+
sb.append("在 AI vibe coding 的时代,\n");
97+
sb.append("每一行模板都坚持手搓。\n");
98+
sb.append("—— 致敬所有古法编程非遗传承者 🙏\n\n");
99+
sb.append("Powered by SpringBootCodeGenerator (2018 - 至今)\n");
100+
sb.append("https://github.com/moshowgame/SpringBootCodeGenerator/\n");
101+
return sb.toString();
102+
}
103+
104+
/**
105+
* XML 声明必须位于文档最前,印章插在声明之后
106+
*/
107+
private static String stampAsXmlComment(String content) {
108+
if (content.startsWith("<?xml")) {
109+
int end = content.indexOf("?>");
110+
if (end > 0) {
111+
String prolog = content.substring(0, end + 2) + "\n";
112+
return prolog + "<!--\n " + LINE_1 + "\n " + LINE_2 + "\n-->\n" + content.substring(end + 2);
113+
}
114+
}
115+
return "<!--\n " + LINE_1 + "\n " + LINE_2 + "\n-->\n" + content;
116+
}
117+
118+
private static String extensionOf(String fileName) {
119+
if (fileName == null) {
120+
return "";
121+
}
122+
String lower = fileName.toLowerCase();
123+
int dot = lower.lastIndexOf('.');
124+
return dot < 0 ? "" : lower.substring(dot + 1);
125+
}
126+
127+
private static String safe(String value) {
128+
return value == null ? "" : value;
129+
}
130+
131+
}

‎src/main/resources/application-dev.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@ OEM:
5151
header: SQL转Java JPA、MYBATIS实现类代码生成平台
5252
keywords: sql转实体类,sql转DAO,SQL转service,SQL转JPA实现,SQL转MYBATIS实现
5353
title: 大狼狗代码生成器
54-
slogan: 👐 Free your hands from boring CRUD—let the code write itself! ⚡
54+
slogan: 🏺 古法编程·非遗传承 | Free your hands from boring CRUD! ⚡
5555
description: <p>💻 SpringBootCodeGenerator,又名 `大狼狗代码生成器`🐺🐶,支持 SQL 一键转 JAVA/JPA/Mybatis/MybatisPlus 等多种模板,轻松搞定 CRUD,彻底解放双手 ✋!只需提供 DDL、SELECT SQL 或简单 JSON 👉 即可生成 生成JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL/CommonMapper 等代码模板。</p><p>🔥🔥🔥 全新 JSqlParser 引擎上线,强力支持 DDL CREATE SQL与 SELECT SQL 解析!欢迎体验 & 反馈 💬!</p><p>👨‍💻 面向开发者的高效利器,已服务数万工程师,欢迎 Star ⭐、Fork 🍴、提 Issue 💬,一起打造更强大的代码生成平台!</p>
5656
author: zhengkai.blog.csdn.net
5757
packageName: com.software.system
58-
copyright: ✨ Powered by <a href="https://zhengkai.blog.csdn.net" target="_blank">Moshow郑锴</a> — may the holy light guide your code, your coffee, and your commits! ⚡🧙‍♂️💻
58+
copyright: 🏺 Powered by <a href="https://zhengkai.blog.csdn.net" target="_blank">Moshow郑锴</a> — 愿你在 AI 时代,既有工具的效率,也有匠人的定力 🙏
5959
returnUtilSuccess: ResponseUtil.success
6060
returnUtilFailure: ResponseUtil.error
6161
outputStr: http://zhengkai.blog.csdn.net

‎src/main/resources/template.json‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
"tier": "main",
44
"templates": [{
55
"id": "10",
6-
"name": "swagger-ui",
7-
"description": "swagger-ui",
8-
"fileName": "swagger-ui.json"
6+
"name": "swagger-ui",
7+
"description": "swagger-ui",
8+
"fileName": "swagger-ui.java"
99
},
1010
{
1111
"id": "11",
@@ -183,7 +183,7 @@
183183
"id": "70",
184184
"name": "beanutil",
185185
"description": "beanutil",
186-
"fileName": "${className}BeanUtil.txt"
186+
"fileName": "${className}BeanUtil.java"
187187
},
188188
{
189189
"id": "71",
@@ -313,7 +313,7 @@
313313
"id": "201",
314314
"name": "qliksense",
315315
"description": "qlik sense",
316-
"fileName": "qliksense.txt"
316+
"fileName": "qliksense.qvs"
317317
}]
318318
},
319319
{

0 commit comments

Comments
 (0)