📝 添加ReadMe文档

This commit is contained in:
Bunny 2025-07-01 17:14:54 +08:00
parent 2a829e477b
commit ec4379abe4
4 changed files with 111 additions and 41 deletions

107
README.md
View File

@ -1,43 +1,90 @@
# 代码生成器 # Bunny Code Generator 🚀
## 内置字段 [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)[![Java Version](https://img.shields.io/badge/JDK-17-green.svg)]()[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.4.3-6DB33F.svg)]()
```java Bunny Code Generator 是一个高效的数据库表结构到代码的生成工具,帮助开发者快速生成高质量的服务端代码,显著提升开发效率。
// vm 不能直接写 `{` 需要转换下
context.put("leftBrace", "{");
// 当前的表名 ## ✨ 核心特性
context.put("tableName", tableMetaData.getTableName());
// 当前表的列信息 - **多数据源支持** - 支持通过数据库连接或直接解析SQL语句生成代码
context.put("columnInfoList", columnInfoList); - **模板引擎自由** - 基于Velocity模板引擎支持完全自定义代码模板
- **灵活输出方式** - 支持即时代码预览和ZIP打包下载两种输出模式
- **智能命名转换** - 自动将表名转换为大/小驼峰命名的类名
- **动态模板选择** - 前端可交互式选择需要生成的模板文件组合
- **注释保留** - 自动将表字段注释带入生成的代码中
// 数据库sql列 ## 🚀 快速入门
context.put("baseColumnList", String.join(",", list));
// 当前日期 ### 前置要求
String date = new SimpleDateFormat(dto.getSimpleDateFormat()).format(new Date());
context.put("date", date);
// 作者名字 - JDK 1.8 或更高版本
context.put("author", dto.getAuthor()); - MySQL 5.7+ (或其他支持的数据库)
- Spring Boot 2.7+
// 每个 Controller 上的请求前缀 ### 安装步骤
context.put("requestMapping", dto.getRequestMapping());
// 表字段的注释内容 1. 克隆仓库:
context.put("comment", dto.getComment()); ```bash
git clone https://github.com/yourusername/bunny-code-generator.git
```
// 设置包名称 2. 配置数据库连接 (`application.yml`)
context.put("package", dto.getPackageName()); ```yaml
bunny:
master:
database: your_database
spring:
datasource:
url: jdbc:mysql://localhost:3306/your_database
username: your_username
password: your_password
driver-class-name: com.mysql.cj.jdbc.Driver
```
// 将类名称转成小驼峰 3. 启动应用:
String toCamelCase = TypeConvertCore.convertToCamelCase(replaceTableName); ```bash
context.put("classLowercaseName", toCamelCase); mvn spring-boot:run
```
// 将类名称转成大驼峰 4. 访问 `http://localhost:8080` 开始使用
String convertToCamelCase = TypeConvertCore.convertToCamelCase(replaceTableName, true);
context.put("classUppercaseName", convertToCamelCase);
```
![wx+alipay](images/wx_alipay.png) ## 🛠️ 模板变量参考
模板中可使用以下预定义变量:
| 变量名 | 描述 | 示例值 |
| -------------------- | ------------------ | ------------------ |
| `tableName` | 原始表名 | `user_info` |
| `classLowercaseName` | 小驼峰类名 | `userInfo` |
| `classUppercaseName` | 大驼峰类名 | `UserInfo` |
| `columnInfoList` | 列信息列表 | `List<ColumnInfo>` |
| `baseColumnList` | SQL列名字符串 | `id,name,age` |
| `package` | 包名 | `com.example.demo` |
| `author` | 作者名 | `YourName` |
| `date` | 当前日期 | `2023-07-20` |
| `comment` | 表注释 | `用户信息表` |
| `requestMapping` | Controller请求前缀 | `/api/user` |
## 🤝 参与贡献
我们欢迎各种形式的贡献!请阅读 [贡献指南](CONTRIBUTING.md) 了解如何参与项目开发。
1. Fork 项目仓库
2. 创建您的特性分支 (`git checkout -b feature/AmazingFeature`)
3. 提交您的更改 (`git commit -m 'Add some AmazingFeature'`)
4. 推送到分支 (`git push origin feature/AmazingFeature`)
5. 发起 Pull Request
## 📄 许可证
本项目采用 MIT 许可证 - 详情请参阅 [LICENSE](LICENSE) 文件。
## ☕ 支持项目
如果这个项目对您有帮助,可以考虑支持我们:
![WeChat & Alipay](images/wx_alipay.png)
---
**Happy Coding!** 🎉

View File

@ -30,7 +30,7 @@ public class VmsUtil {
// 大驼峰名称 // 大驼峰名称
String CamelCase = MysqlTypeConvertUtil.convertToCamelCase(className, true); String CamelCase = MysqlTypeConvertUtil.convertToCamelCase(className, true);
// 小驼峰名称 // 小驼峰名称
String camelCase = MysqlTypeConvertUtil.convertToCamelCase(className); String smallCamelCase = MysqlTypeConvertUtil.convertToCamelCase(className);
// 当前文件名 // 当前文件名
String filename = splitPaths[splitPathsSize]; String filename = splitPaths[splitPathsSize];
@ -52,8 +52,9 @@ public class VmsUtil {
filename = CamelCase + typeMappingsFilename + "." + extension; filename = CamelCase + typeMappingsFilename + "." + extension;
} }
if (filename.contains("vue") && !filename.contains("index")) { if ((filename.contains("vue") || filename.contains("ts") || filename.contains("js"))
filename = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, camelCase) + "-" + name + "." + extension; && !filename.contains("index")) {
filename = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, smallCamelCase) + "-" + name + "." + extension;
} }
splitPaths[splitPathsSize] = filename; splitPaths[splitPathsSize] = filename;

View File

@ -129,7 +129,12 @@ const MainForm = {
</button> </button>
</div> </div>
<div class="col-md-4 btn-group"> <div class="col-md-4 btn-group">
<button class="btn btn-primary" data-bs-title="生成全部已经选择的数据表" data-bs-toggle="tooltip" <button class="btn btn-primary shadow-sm" disabled type="button"
v-if="generatorCodeLoading">
<span aria-hidden="true" class="spinner-grow spinner-grow-sm"></span>
<span role="status">生成选中表...</span>
</button>
<button v-else class="btn btn-primary" data-bs-title="生成全部已经选择的数据表" data-bs-toggle="tooltip"
type="submit"> type="submit">
生成选中表 生成选中表
</button> </button>
@ -137,7 +142,13 @@ const MainForm = {
@click="onClearGeneratorData">清空生成记录</button> @click="onClearGeneratorData">清空生成记录</button>
</div> </div>
<div class="col-md-4 d-grid gap-2"> <div class="col-md-4 d-grid gap-2">
<button class="btn btn-primary text-white" type="button" @click="onDownloadZip">下载ZIP</button> <button class="btn btn-primary shadow-sm" disabled type="button"
v-if="downloadLoading">
<span aria-hidden="true" class="spinner-grow spinner-grow-sm"></span>
<span role="status">下载ZIP...</span>
</button>
<button v-else class="btn btn-primary text-white" type="button" @click="onDownloadZip">下载ZIP</button>
</div> </div>
</div> </div>
</form> </form>
@ -151,6 +162,8 @@ const MainForm = {
onGeneratorCode: {type: Function, required: true}, onGeneratorCode: {type: Function, required: true},
// 清空生成记录 // 清空生成记录
onClearGeneratorData: {type: Function, required: true}, onClearGeneratorData: {type: Function, required: true},
// 生成代码加载
generatorCodeLoading: {type: Boolean, required: true},
}, },
data() { data() {
return { return {
@ -169,7 +182,8 @@ const MainForm = {
tablePrefixes: '', tablePrefixes: '',
webTemplates: '', webTemplates: '',
serverTemplates: '' serverTemplates: ''
} },
downloadLoading: ref(false),
} }
}, },
methods: { methods: {
@ -273,6 +287,7 @@ const MainForm = {
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async onDownloadZip() { async onDownloadZip() {
this.downloadLoading = true;
try { try {
const response = await axiosInstance({ const response = await axiosInstance({
url: "/vms/downloadByZip", url: "/vms/downloadByZip",
@ -314,6 +329,8 @@ const MainForm = {
} catch (error) { } catch (error) {
console.error('下载失败:', error); console.error('下载失败:', error);
} }
this.downloadLoading = false;
}, },
/** /**

View File

@ -65,9 +65,8 @@
v-model:db-select="dbSelect" v-model:table-select="tableSelect"></main-card> v-model:db-select="dbSelect" v-model:table-select="tableSelect"></main-card>
<!-- 填写生成表单 --> <!-- 填写生成表单 -->
<main-form :on-clear-generator-data="onClearGeneratorData" :on-generator-code="onGeneratorCode" <main-form :generator-code-loading="generatorCodeLoading" :on-clear-generator-data="onClearGeneratorData"
ref="mainFormRef" :on-generator-code="onGeneratorCode" ref="mainFormRef" v-model:form="form"></main-form>
v-model:form="form"></main-form>
<!-- 表格显示 --> <!-- 表格显示 -->
<main-table :db-select="dbSelect" :loading="loading" :on-generator-code="onGeneratorCode" <main-table :db-select="dbSelect" :loading="loading" :on-generator-code="onGeneratorCode"
@ -113,6 +112,8 @@
rawTableList: ref([]), rawTableList: ref([]),
// 是否加载 // 是否加载
loading: ref(false), loading: ref(false),
// 是否正在生成
generatorCodeLoading: ref(false),
// 提交的表单 // 提交的表单
form: ref({ form: ref({
// 作者名称 // 作者名称
@ -164,6 +165,7 @@
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async onGeneratorCode() { async onGeneratorCode() {
this.generatorCodeLoading = true;
// 验证表单是否通过 // 验证表单是否通过
const isValidate = this.$refs.mainFormRef.validateForm(); const isValidate = this.$refs.mainFormRef.validateForm();
if (!isValidate) return; if (!isValidate) return;
@ -172,12 +174,15 @@
const {data, code, message} = await axiosInstance.post("/vms/generator", this.form); const {data, code, message} = await axiosInstance.post("/vms/generator", this.form);
// 判断是否请求成功 // 判断是否请求成功
if (code !== 200) return; if (code !== 200) {
else antd.message.success(message); this.generatorCodeLoading = false;
return;
} else antd.message.success(message);
// 显示生成的页面 // 显示生成的页面
this.generatorData = data; this.generatorData = data;
this.generatorPageFlag = true; this.generatorPageFlag = true;
this.generatorCodeLoading = false;
// 等待 DOM 更新,之后手动更新代码高亮 // 等待 DOM 更新,之后手动更新代码高亮
await this.$nextTick(); await this.$nextTick();