完善代码生成项目功能和测试数据
This commit is contained in:
@@ -1,96 +1,243 @@
|
|||||||
<p align="center">
|
# RuoYi-Vue 代码生成平台
|
||||||
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
|
|
||||||
</p>
|
|
||||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.8.8</h1>
|
|
||||||
<h4 align="center">基于SpringBoot+Vue前后端分离的Java快速开发框架</h4>
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Vue/stargazers"><img src="https://gitee.com/y_project/RuoYi-Vue/badge/star.svg?theme=dark"></a>
|
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.8.8-brightgreen.svg"></a>
|
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Vue/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
## 平台简介
|
基于 RuoYi-Vue v3.8.8 二次开发的前后端分离后台管理系统。项目保留若依的用户、角色、菜单、日志、监控、定时任务、代码生成等基础能力,并在 `ruoyi-generator` 与 `ruoyi-ui/src/views/generator` 下扩展了项目级代码生成平台能力。
|
||||||
|
|
||||||
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
|
当前仓库更适合按“后台基础框架 + 可配置代码生成平台”来理解:先用若依提供认证、权限、菜单、数据权限、日志和基础运维能力,再围绕项目、数据源、模板、模块、代码片段和项目结构生成完整代码包。
|
||||||
|
|
||||||
* 前端采用Vue、Element UI。
|
## 技术栈
|
||||||
* 后端采用Spring Boot、Spring Security、Redis & Jwt。
|
|
||||||
* 权限认证使用Jwt,支持多终端认证系统。
|
|
||||||
* 支持加载动态权限菜单,多方式轻松权限控制。
|
|
||||||
* 高效率开发,使用代码生成器可以一键生成前后端代码。
|
|
||||||
* 提供了技术栈([Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev))版本[RuoYi-Vue3](https://github.com/yangzongzhuan/RuoYi-Vue3),保持同步更新。
|
|
||||||
* 提供了单应用版本[RuoYi-Vue-fast](https://github.com/yangzongzhuan/RuoYi-Vue-fast),Oracle版本[RuoYi-Vue-Oracle](https://github.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。
|
|
||||||
* 不分离版本,请移步[RuoYi](https://gitee.com/y_project/RuoYi),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
|
|
||||||
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)
|
|
||||||
* 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)
|
|
||||||
|
|
||||||
## 内置功能
|
| 层级 | 技术 |
|
||||||
|
| --- | --- |
|
||||||
|
| 后端 | Java 8、Spring Boot 2.5.15、Spring Framework 5.3.39、Spring Security 5.7.12 |
|
||||||
|
| 数据访问 | MyBatis、PageHelper、Druid、MySQL |
|
||||||
|
| 缓存与任务 | Redis、Quartz |
|
||||||
|
| 接口与工具 | JWT、Swagger/Springfox 3、Velocity、Fastjson2、Apache POI、OSHI |
|
||||||
|
| 前端 | Vue 2.6.12、Vue CLI 4.4.6、Element UI 2.15.14、Vue Router、Vuex、Axios |
|
||||||
|
| 构建 | Maven、npm |
|
||||||
|
|
||||||
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
## 架构概览
|
||||||
2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
|
|
||||||
3. 岗位管理:配置系统用户所属担任职务。
|
|
||||||
4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。
|
|
||||||
5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
|
|
||||||
6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
|
|
||||||
7. 参数管理:对系统动态配置常用参数。
|
|
||||||
8. 通知公告:系统通知公告信息发布维护。
|
|
||||||
9. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
|
|
||||||
10. 登录日志:系统登录日志记录查询包含登录异常。
|
|
||||||
11. 在线用户:当前系统中活跃用户状态监控。
|
|
||||||
12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
|
|
||||||
13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。
|
|
||||||
14. 系统接口:根据业务代码自动生成相关的api接口文档。
|
|
||||||
15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
|
|
||||||
16. 缓存监控:对系统的缓存信息查询,命令统计等。
|
|
||||||
17. 在线构建器:拖动表单元素生成相应的HTML代码。
|
|
||||||
18. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
|
|
||||||
|
|
||||||
## 在线体验
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
A["浏览器 / ruoyi-ui"] --> B["Vue DevServer<br/>/dev-api 代理"]
|
||||||
|
B --> C["ruoyi-admin<br/>Spring Boot 入口"]
|
||||||
|
C --> D["ruoyi-framework<br/>安全、配置、Web 基础设施"]
|
||||||
|
C --> E["ruoyi-system<br/>用户、角色、菜单、字典等"]
|
||||||
|
C --> F["ruoyi-generator<br/>代码生成与扩展平台"]
|
||||||
|
C --> G["ruoyi-quartz<br/>定时任务"]
|
||||||
|
C --> H["MySQL"]
|
||||||
|
C --> I["Redis"]
|
||||||
|
F --> J["Velocity 模板"]
|
||||||
|
F --> K["代码预览 / ZIP 下载"]
|
||||||
|
```
|
||||||
|
|
||||||
- admin/admin123
|
## 目录结构
|
||||||
- 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。
|
|
||||||
|
|
||||||
演示地址:http://vue.ruoyi.vip
|
| 路径 | 说明 |
|
||||||
文档地址:http://doc.ruoyi.vip
|
| --- | --- |
|
||||||
|
| `ruoyi-admin` | 后端启动入口,打包为可执行 `war`;包含 Web Controller、配置文件和静态资源入口。 |
|
||||||
|
| `ruoyi-framework` | 若依框架层,承载安全认证、权限校验、数据源、Web 配置、拦截器、异步任务等基础能力。 |
|
||||||
|
| `ruoyi-system` | 系统管理业务模块,包括用户、角色、菜单、部门、岗位、字典、参数、通知公告、日志等。 |
|
||||||
|
| `ruoyi-quartz` | 定时任务模块,封装 Quartz 任务、任务日志和调度管理。 |
|
||||||
|
| `ruoyi-generator` | 代码生成模块;包含若依原生表驱动代码生成,以及本项目扩展的项目、模板、数据源、模块、代码片段、项目结构等功能。 |
|
||||||
|
| `ruoyi-common` | 通用工具、常量、注解、基础实体、响应对象、异常、工具类等公共代码。 |
|
||||||
|
| `ruoyi-ui` | Vue 2 + Element UI 前端工程。 |
|
||||||
|
| `sql` | 数据库初始化与扩展脚本。 |
|
||||||
|
| `doc` | 代码生成平台规划文档。 |
|
||||||
|
| `docs` | 部分扩展 Controller 的接口说明文档。 |
|
||||||
|
| `bin`、`ry.bat`、`ry.sh` | 启停脚本与辅助脚本。 |
|
||||||
|
|
||||||
## 演示图
|
## 核心功能
|
||||||
|
|
||||||
<table>
|
### 若依基础能力
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/cd1f90be5f2684f4560c9519c0f2a232ee8.jpg"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-8074972883b5ba0622e13246738ebba237a.png"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-9f88719cdfca9af2e58b352a20e23d43b12.png"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-39bf2584ec3a529b0d5a3b70d15c9b37646.png"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-936ec82d1f4872e1bc980927654b6007307.png"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-b2d62ceb95d2dd9b3fbe157bb70d26001e9.png"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-d67451d308b7a79ad6819723396f7c3d77a.png"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-8370a0d02977eebf6dbf854c8450293c937.png"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-49003ed83f60f633e7153609a53a2b644f7.png"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-d4fe726319ece268d4746602c39cffc0621.png"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/b6115bc8c31de52951982e509930b20684a.jpg"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-5e4daac0bb59612c5038448acbcef235e3a.png"/></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
- 用户、角色、菜单、部门、岗位管理。
|
||||||
|
- 字典、参数、通知公告管理。
|
||||||
|
- 登录日志、操作日志、在线用户管理。
|
||||||
|
- 服务监控、缓存监控、Druid 连接池监控。
|
||||||
|
- Quartz 定时任务与任务日志。
|
||||||
|
- Swagger 接口文档、表单构建、若依原生代码生成。
|
||||||
|
|
||||||
## 若依前后端分离交流群
|
### 代码生成平台扩展
|
||||||
|
|
||||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=5bVB1og) [](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [](https://jq.qq.com/?_wv=1027&k=51G72yr) [](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [](https://jq.qq.com/?_wv=1027&k=SpyH2875) [](https://jq.qq.com/?_wv=1027&k=tKEt51dz) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=0vBbSb0ztbBgVtn3kJS-Q4HUNYwip89G&authKey=8irq5PhutrZmWIvsUsklBxhj57l%2F1nOZqjzigkXZVoZE451GG4JHPOqW7AW6cf0T&noverify=0&group_code=143961921) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ZFAPAbp09S2ltvwrJzp7wGlbopsc0rwi&authKey=HB2cxpxP2yspk%2Bo3WKTBfktRCccVkU26cgi5B16u0KcAYrVu7sBaE7XSEqmMdFQp&noverify=0&group_code=174951577) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Fn2aF5IHpwsy8j6VlalNJK6qbwFLFHat&authKey=uyIT%2B97x2AXj3odyXpsSpVaPMC%2Bidw0LxG5MAtEqlrcBcWJUA%2FeS43rsF1Tg7IRJ&noverify=0&group_code=161281055) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=XIzkm_mV2xTsUtFxo63bmicYoDBA6Ifm&authKey=dDW%2F4qsmw3x9govoZY9w%2FoWAoC4wbHqGal%2BbqLzoS6VBarU8EBptIgPKN%2FviyC8j&noverify=0&group_code=138988063) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DkugnCg68PevlycJSKSwjhFqfIgrWWwR&authKey=pR1Pa5lPIeGF%2FFtIk6d%2FGB5qFi0EdvyErtpQXULzo03zbhopBHLWcuqdpwY241R%2F&noverify=0&group_code=151450850) 点击按钮入群。
|
| 功能 | 后端接口前缀 | 前端位置 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 数据源管理 | `/generator/datasource` | `ruoyi-ui/src/views/generator/datasource` |
|
||||||
|
| 项目管理 | `/generator/project` | `ruoyi-ui/src/views/generator/project` |
|
||||||
|
| 项目关联表 | `/generator/project/table` | `ProjectTableConfig.vue` |
|
||||||
|
| 项目关联模块 | `/generator/project/module` | `ProjectModuleConfig.vue` |
|
||||||
|
| 项目模板配置 | `/generator/project/template` | `ProjectTemplateConfig.vue` |
|
||||||
|
| 项目结构树 | `/generator/structure` | `ruoyi-ui/src/views/generator/structure` |
|
||||||
|
| 模板管理 | `/generator/template` | `ruoyi-ui/src/views/generator/template` |
|
||||||
|
| 模板文件管理 | `/generator/templateFile` | `templateFile.js` 与模板相关页面 |
|
||||||
|
| 功能模块管理 | `/generator/module` | `ruoyi-ui/src/views/generator/module` |
|
||||||
|
| 代码片段管理 | `/generator/snippet` | `ruoyi-ui/src/views/generator/snippet` |
|
||||||
|
| 原生表代码生成 | `/tool/gen` | `ruoyi-ui/src/views/tool/gen` |
|
||||||
|
|
||||||
|
扩展生成链路大致为:维护数据源和数据表,配置项目基本信息、项目关联表、模块、模板和结构树,通过 `GenProjectController` 预览或下载项目结构与生成代码。
|
||||||
|
|
||||||
|
## 本地启动
|
||||||
|
|
||||||
|
### 1. 环境准备
|
||||||
|
|
||||||
|
- JDK 1.8
|
||||||
|
- Maven 3.6+
|
||||||
|
- MySQL 5.7/8.0
|
||||||
|
- Redis 5+
|
||||||
|
- Node.js:`package.json` 要求 `>=8.9`,实际开发建议使用 Node 14/16 LTS
|
||||||
|
- npm 6+
|
||||||
|
|
||||||
|
### 2. 初始化数据库
|
||||||
|
|
||||||
|
默认数据库配置在 `ruoyi-admin/src/main/resources/application-druid.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
druid:
|
||||||
|
master:
|
||||||
|
url: jdbc:mysql://localhost:3306/ry
|
||||||
|
username: root
|
||||||
|
password: 123456
|
||||||
|
```
|
||||||
|
|
||||||
|
创建数据库:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE DATABASE ry DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
|
||||||
|
```
|
||||||
|
|
||||||
|
新库推荐直接导入完整脚本:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mysql -uroot -p ry < sql/db.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
`sql/db.sql` 已整合若依基础表、Quartz 调度表、代码生成平台扩展表、初始化数据、代码生成平台菜单和按钮权限。分散脚本仍可作为增量或排查参考:
|
||||||
|
|
||||||
|
1. `sql/ry_20240629.sql`:若依基础表与基础数据。
|
||||||
|
2. `sql/quartz.sql`:Quartz 调度表。
|
||||||
|
3. `sql/gen_project.sql`:项目基础信息表 `gen_project`。
|
||||||
|
4. `sql/module_management.sql`:功能模块、代码片段、项目模块关系表。
|
||||||
|
5. `sql/gen_table_project_rel.sql`:项目与代码生成表关系。
|
||||||
|
6. `sql/sys_project_structure.sql`:项目结构节点表与初始化结构。
|
||||||
|
7. `sql/add_create_table_sql_field.sql`:给 `gen_table` 增加建表 SQL 字段。
|
||||||
|
8. `ruoyi-generator/sql/template_file_update.sql`:模板文件表增量字段。
|
||||||
|
|
||||||
|
### 3. 配置后端
|
||||||
|
|
||||||
|
重点检查以下配置:
|
||||||
|
|
||||||
|
| 文件 | 关键项 |
|
||||||
|
| --- | --- |
|
||||||
|
| `ruoyi-admin/src/main/resources/application.yml` | `server.port` 默认 `8080`,`server.servlet.context-path` 默认 `/`,Redis 地址,上传目录 `ruoyi.profile`,Swagger 开关。 |
|
||||||
|
| `ruoyi-admin/src/main/resources/application-druid.yml` | MySQL 地址、账号、密码、Druid 控制台账号。 |
|
||||||
|
| `ruoyi-generator/src/main/resources/generator.yml` | 代码生成默认作者、包名、表前缀策略。 |
|
||||||
|
|
||||||
|
启动后端:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn clean install -DskipTests
|
||||||
|
mvn -pl ruoyi-admin -am spring-boot:run
|
||||||
|
```
|
||||||
|
|
||||||
|
也可以打包后运行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn clean package -DskipTests
|
||||||
|
java -jar ruoyi-admin/target/ruoyi-admin.war
|
||||||
|
```
|
||||||
|
|
||||||
|
后端默认地址:`http://localhost:8080`
|
||||||
|
|
||||||
|
### 4. 启动前端
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ruoyi-ui
|
||||||
|
npm install --registry=https://registry.npmmirror.com
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
前端默认端口来自 `ruoyi-ui/vue.config.js`,为 `80`。开发环境的 `VUE_APP_BASE_API=/dev-api`,会代理到 `http://localhost:8080/`。
|
||||||
|
|
||||||
|
浏览器访问:`http://localhost:80`
|
||||||
|
|
||||||
|
默认账号:
|
||||||
|
|
||||||
|
```text
|
||||||
|
admin / admin123
|
||||||
|
```
|
||||||
|
|
||||||
|
如果本机 80 端口被占用,可以临时指定端口:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Windows PowerShell
|
||||||
|
$env:port=81
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## 构建与发布
|
||||||
|
|
||||||
|
后端构建:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn clean package -DskipTests
|
||||||
|
```
|
||||||
|
|
||||||
|
产物位于:
|
||||||
|
|
||||||
|
```text
|
||||||
|
ruoyi-admin/target/ruoyi-admin.war
|
||||||
|
```
|
||||||
|
|
||||||
|
前端构建:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ruoyi-ui
|
||||||
|
npm run build:prod
|
||||||
|
```
|
||||||
|
|
||||||
|
产物位于:
|
||||||
|
|
||||||
|
```text
|
||||||
|
ruoyi-ui/dist
|
||||||
|
```
|
||||||
|
|
||||||
|
生产环境需要注意:
|
||||||
|
|
||||||
|
- `ruoyi-ui/vue.config.js` 中生产 `publicPath` 为 `/yidaima`。
|
||||||
|
- `ruoyi-ui/.env.production` 中接口前缀为 `/prod-api`。
|
||||||
|
- 如果部署在子路径或网关后面,需要同步调整 Nginx、前端 `publicPath`、接口代理和后端 `context-path`。
|
||||||
|
|
||||||
|
## 常用入口
|
||||||
|
|
||||||
|
| 入口 | 地址 |
|
||||||
|
| --- | --- |
|
||||||
|
| 后端服务 | `http://localhost:8080` |
|
||||||
|
| 前端页面 | `http://localhost:80` |
|
||||||
|
| Swagger UI | `http://localhost:8080/swagger-ui/index.html` |
|
||||||
|
| Druid 控制台 | `http://localhost:8080/druid`,默认 `ruoyi / 123456` |
|
||||||
|
|
||||||
|
## 开发约定
|
||||||
|
|
||||||
|
- 后端扩展 Controller 主要位于 `ruoyi-generator/src/main/java/com/ruoyi/generator/controller`。
|
||||||
|
- 后端扩展实体、Mapper、Service 位于 `ruoyi-generator/src/main/java/com/ruoyi/generator/{domain,mapper,service}`。
|
||||||
|
- MyBatis XML 位于 `ruoyi-generator/src/main/resources/mapper/generator`。
|
||||||
|
- 前端接口封装位于 `ruoyi-ui/src/api/generator`。
|
||||||
|
- 前端扩展页面位于 `ruoyi-ui/src/views/generator`。
|
||||||
|
- 权限标识沿用若依格式,例如 `generator:project:list`、`generator:template:add`、`tool:gen:preview`。
|
||||||
|
- 代码生成模板分为若依默认模板 `ruoyi-generator/src/main/resources/vm` 与扩展模板目录 `ruoyi-generator/src/main/resources/qing`。
|
||||||
|
|
||||||
|
## 文档索引
|
||||||
|
|
||||||
|
- `doc/code-generator-platform.md`:代码生成平台功能规划。
|
||||||
|
- `docs/*.md`:扩展 Controller 的接口说明。
|
||||||
|
- `ruoyi-ui/README.md`:前端工程原始启动说明。
|
||||||
|
- 若依官方文档:`http://doc.ruoyi.vip`
|
||||||
|
|
||||||
|
## 排查提示
|
||||||
|
|
||||||
|
- 后端启动失败优先检查 MySQL、Redis 是否启动,以及 `application-druid.yml` 中数据库账号密码是否正确。
|
||||||
|
- 前端请求 404 或跨域异常时,检查 `.env.development` 的 `VUE_APP_BASE_API` 与 `vue.config.js` 的代理目标。
|
||||||
|
- 使用生产构建部署到非根路径时,检查 `/yidaima`、`/prod-api` 与网关转发规则是否一致。
|
||||||
|
- 生成平台页面报表不存在时,优先核对扩展 SQL 是否已导入,尤其是模板、数据源、项目结构和项目关联表。
|
||||||
|
|||||||
@@ -35,6 +35,18 @@
|
|||||||
<artifactId>druid-spring-boot-starter</artifactId>
|
<artifactId>druid-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -117,10 +117,7 @@ public class GenProjectServiceImpl implements IGenProjectService {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<Map<String, Object>> getProjectStructure(Long projectId, String type) {
|
public List<Map<String, Object>> getProjectStructure(Long projectId, String type) {
|
||||||
GenProject project = genProjectMapper.selectGenProjectById(projectId);
|
GenProject project = getRequiredProject(projectId);
|
||||||
if (project == null) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<GenTable> projectTables = genTableMapper.selectGenTablesByProjectId(projectId);
|
List<GenTable> projectTables = genTableMapper.selectGenTablesByProjectId(projectId);
|
||||||
project.setTables(projectTables);
|
project.setTables(projectTables);
|
||||||
@@ -128,95 +125,39 @@ public class GenProjectServiceImpl implements IGenProjectService {
|
|||||||
List<Map<String, Object>> structure = new ArrayList<>();
|
List<Map<String, Object>> structure = new ArrayList<>();
|
||||||
|
|
||||||
// 获取项目模板
|
// 获取项目模板
|
||||||
SysProjectTemplate projectTemplate = sysProjectTemplateService.selectSysProjectTemplateByProjectAndType(project.getProjectId(), type);
|
SysProjectTemplate projectTemplate = getRequiredProjectTemplate(project, type);
|
||||||
if (projectTemplate == null) {
|
|
||||||
return structure;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取模板关联的项目结构节点
|
// 获取模板关联的项目结构节点
|
||||||
List<SysProjectStructure> structureNodes = sysProjectStructureService.selectProjectStructureListByModule(project.getProjectId(), projectTemplate.getTemplateId());
|
List<SysProjectStructure> structureNodes = sysProjectStructureService.selectProjectStructureListByModule(project.getProjectId(), projectTemplate.getTemplateId());
|
||||||
|
|
||||||
// 构建树形结构
|
// 构建树形结构
|
||||||
Map<Long, Map<String, Object>> nodeMap = new HashMap<>();
|
Map<Long, SysProjectStructure> sourceNodeMap = new HashMap<>();
|
||||||
|
Map<String, Map<String, Object>> nodeMap = new LinkedHashMap<>();
|
||||||
for (SysProjectStructure node : structureNodes) {
|
for (SysProjectStructure node : structureNodes) {
|
||||||
Map<String, Object> nodeData = new HashMap<>();
|
sourceNodeMap.put(node.getNodeId(), node);
|
||||||
String nodeName = node.getNodeName();
|
if (isTableScopedNode(node)) {
|
||||||
if(nodeName.contains("{projectName}")){
|
for (GenTable table : projectTables) {
|
||||||
nodeName = nodeName.replace("{projectName}", project.getProjectFileName());
|
Map<String, Object> tableNodeData = createStructureNodeData(node, project, table);
|
||||||
} else if(nodeName.contains("{packageName}")){
|
nodeMap.put(getNodeKey(node.getNodeId(), table.getTableId()), tableNodeData);
|
||||||
nodeName = nodeName.replace("{packageName}", project.getPackageName());
|
|
||||||
}
|
|
||||||
Long tableId = node.getTableId();
|
|
||||||
if(tableId != null && tableId == 0){
|
|
||||||
for(GenTable table : projectTables){
|
|
||||||
Map<String, Object> tableNodeData = new HashMap<>();
|
|
||||||
String tableNodeName = nodeName;
|
|
||||||
if(tableNodeName.contains("{ClassName}")){
|
|
||||||
tableNodeName = tableNodeName.replace("{ClassName}", table.getClassName());
|
|
||||||
}
|
|
||||||
Long nodeId = node.getNodeId() * 1000 + table.getTableId();
|
|
||||||
tableNodeData.put("id", nodeId);
|
|
||||||
tableNodeData.put("name", tableNodeName);
|
|
||||||
tableNodeData.put("type", node.getNodeType());
|
|
||||||
tableNodeData.put("category", node.getCategory());
|
|
||||||
tableNodeData.put("tableId", table.getTableId());
|
|
||||||
nodeMap.put(nodeId, tableNodeData);
|
|
||||||
}
|
}
|
||||||
} else{
|
} else {
|
||||||
nodeData.put("id", node.getNodeId());
|
Map<String, Object> nodeData = createStructureNodeData(node, project, null);
|
||||||
nodeData.put("name", nodeName);
|
nodeMap.put(getNodeKey(node.getNodeId(), null), nodeData);
|
||||||
nodeData.put("type", node.getNodeType());
|
|
||||||
nodeData.put("category", node.getCategory());
|
|
||||||
nodeData.put("tableId", tableId);
|
|
||||||
nodeMap.put(node.getNodeId(), nodeData);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ("folder".equals(node.getNodeType())) {
|
|
||||||
nodeData.put("children", new ArrayList<>());
|
|
||||||
nodeMap.put(node.getNodeId(), nodeData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建父子关系
|
// 构建父子关系
|
||||||
for (SysProjectStructure node : structureNodes) {
|
for (SysProjectStructure node : structureNodes) {
|
||||||
if (node.getTableId() != null && node.getTableId() == 0) {
|
if (isTableScopedNode(node)) {
|
||||||
// 处理表特定的节点
|
// 处理表特定的节点
|
||||||
for (GenTable table : projectTables) {
|
for (GenTable table : projectTables) {
|
||||||
Long nodeId = node.getNodeId() * 1000 + table.getTableId();
|
Map<String, Object> nodeData = nodeMap.get(getNodeKey(node.getNodeId(), table.getTableId()));
|
||||||
Map<String, Object> nodeData = nodeMap.get(nodeId);
|
addNodeToParent(structure, nodeData, node, nodeMap, sourceNodeMap, table);
|
||||||
if (nodeData != null) {
|
|
||||||
if (node.getParentId() == 0) {
|
|
||||||
structure.add(nodeData);
|
|
||||||
} else {
|
|
||||||
Map<String, Object> parentNode = nodeMap.get(node.getParentId());
|
|
||||||
if (parentNode != null) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
List<Map<String, Object>> children = (List<Map<String, Object>>) parentNode.get("children");
|
|
||||||
if (children != null) {
|
|
||||||
children.add(nodeData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 处理普通节点
|
// 处理普通节点
|
||||||
Map<String, Object> nodeData = nodeMap.get(node.getNodeId());
|
Map<String, Object> nodeData = nodeMap.get(getNodeKey(node.getNodeId(), null));
|
||||||
if (nodeData != null) {
|
addNodeToParent(structure, nodeData, node, nodeMap, sourceNodeMap, null);
|
||||||
if (node.getParentId() == 0) {
|
|
||||||
structure.add(nodeData);
|
|
||||||
} else {
|
|
||||||
Map<String, Object> parentNode = nodeMap.get(node.getParentId());
|
|
||||||
if (parentNode != null) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
List<Map<String, Object>> children = (List<Map<String, Object>>) parentNode.get("children");
|
|
||||||
if (children != null) {
|
|
||||||
children.add(nodeData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,10 +166,7 @@ public class GenProjectServiceImpl implements IGenProjectService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] downloadStructure(Long projectId, String type) {
|
public byte[] downloadStructure(Long projectId, String type) {
|
||||||
GenProject project = genProjectMapper.selectGenProjectById(projectId);
|
GenProject project = getRequiredProject(projectId);
|
||||||
if (project == null) {
|
|
||||||
throw new ServiceException("项目不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<GenTable> projectTables = genTableMapper.selectGenTablesByProjectId(projectId);
|
List<GenTable> projectTables = genTableMapper.selectGenTablesByProjectId(projectId);
|
||||||
project.setTables(projectTables);
|
project.setTables(projectTables);
|
||||||
@@ -296,7 +234,7 @@ public class GenProjectServiceImpl implements 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)
|
||||||
{
|
{
|
||||||
Map<String, String> dataMap = new LinkedHashMap<>();
|
Map<String, String> dataMap = new LinkedHashMap<>();
|
||||||
GenProject project = genProjectMapper.selectGenProjectById(projectId);
|
GenProject project = getRequiredProject(projectId);
|
||||||
List<GenTable> projectTables = genTableMapper.selectGenTablesByProjectId(projectId);
|
List<GenTable> projectTables = genTableMapper.selectGenTablesByProjectId(projectId);
|
||||||
project.setTables(projectTables);
|
project.setTables(projectTables);
|
||||||
|
|
||||||
@@ -305,38 +243,15 @@ public class GenProjectServiceImpl implements IGenProjectService {
|
|||||||
List<SysProjectModule> modules = sysProjectModuleService.selectSysProjectModuleList(projectModuleFilter);
|
List<SysProjectModule> modules = sysProjectModuleService.selectSysProjectModuleList(projectModuleFilter);
|
||||||
|
|
||||||
VelocityInitializer.initVelocity();
|
VelocityInitializer.initVelocity();
|
||||||
VelocityContext context = null;
|
|
||||||
String tplCategory = "";
|
|
||||||
|
|
||||||
if(!Objects.isNull(tableId) && tableId != -1){
|
|
||||||
// 查询表信息
|
|
||||||
GenTable table = genTableMapper.selectGenTableById(tableId);
|
|
||||||
table.setModules(modules);
|
|
||||||
tplCategory = table.getTplCategory();
|
|
||||||
table.setPackageName(project.getPackageName());
|
|
||||||
// 设置主子表信息
|
|
||||||
setSubTable(table);
|
|
||||||
// 设置主键列信息
|
|
||||||
setPkColumn(table);
|
|
||||||
// 设置代码片段
|
|
||||||
setCodeSnippet(table);
|
|
||||||
|
|
||||||
context = VelocityUtils.prepareContext(table);
|
|
||||||
} else{
|
|
||||||
context = VelocityUtils.prepareContextProject(project);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取模板列表
|
// 获取模板列表
|
||||||
SysProjectTemplate projectTemplate = sysProjectTemplateService.selectSysProjectTemplateByProjectAndType(project.getProjectId(), type);
|
SysProjectTemplate projectTemplate = getRequiredProjectTemplate(project, type);
|
||||||
List<TemplateFile> templateFileList = templateFileService.selectTemplateFilesByTemplateId(projectTemplate.getTemplateId());
|
List<TemplateFile> templateFileList = getRequiredTemplateFiles(projectTemplate.getTemplateId());
|
||||||
for (TemplateFile templateFile : templateFileList)
|
for (TemplateFile templateFile : templateFileList)
|
||||||
{
|
{
|
||||||
if(templateFile.getFileName().contains(keyword)){
|
if(matchesTemplateFile(templateFile, keyword)){
|
||||||
// 渲染模板
|
// 渲染模板
|
||||||
StringWriter sw = new StringWriter();
|
dataMap.put(templateFile.getFileName(), renderTemplate(project, tableId, modules, templateFile));
|
||||||
String tplContent = templateFile.getFileContent();
|
|
||||||
Velocity.evaluate(context, sw, "", tplContent);
|
|
||||||
dataMap.put(templateFile.getFileName(), sw.toString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dataMap;
|
return dataMap;
|
||||||
@@ -351,67 +266,219 @@ public class GenProjectServiceImpl implements IGenProjectService {
|
|||||||
List<SysProjectModule> modules = sysProjectModuleService.selectSysProjectModuleList(projectModuleFilter);
|
List<SysProjectModule> modules = sysProjectModuleService.selectSysProjectModuleList(projectModuleFilter);
|
||||||
|
|
||||||
VelocityInitializer.initVelocity();
|
VelocityInitializer.initVelocity();
|
||||||
VelocityContext context = null;
|
|
||||||
String tplCategory = "";
|
|
||||||
|
|
||||||
if(!Objects.isNull(tableId) && tableId != -1){
|
|
||||||
// 查询表信息
|
|
||||||
GenTable table = genTableMapper.selectGenTableById(tableId);
|
|
||||||
table.setModules(modules);
|
|
||||||
tplCategory = table.getTplCategory();
|
|
||||||
table.setPackageName(project.getPackageName());
|
|
||||||
// 设置主子表信息
|
|
||||||
setSubTable(table);
|
|
||||||
// 设置主键列信息
|
|
||||||
setPkColumn(table);
|
|
||||||
// 设置代码片段
|
|
||||||
setCodeSnippet(table);
|
|
||||||
|
|
||||||
context = VelocityUtils.prepareContext(table);
|
|
||||||
} else {
|
|
||||||
context = VelocityUtils.prepareContextProject(project);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取模板列表
|
// 获取模板列表
|
||||||
SysProjectTemplate projectTemplate = sysProjectTemplateService.selectSysProjectTemplateByProjectAndType(project.getProjectId(), type);
|
SysProjectTemplate projectTemplate = getRequiredProjectTemplate(project, type);
|
||||||
List<TemplateFile> templateFileList = templateFileService.selectTemplateFilesByTemplateId(projectTemplate.getTemplateId());
|
List<TemplateFile> templateFileList = getRequiredTemplateFiles(projectTemplate.getTemplateId());
|
||||||
for (TemplateFile templateFile : templateFileList)
|
for (TemplateFile templateFile : templateFileList)
|
||||||
{
|
{
|
||||||
if(templateFile.getFileName().contains(category)){
|
if(matchesTemplateFile(templateFile, category)){
|
||||||
try {
|
try {
|
||||||
StringWriter sw = new StringWriter();
|
return renderTemplate(project, tableId, modules, templateFile);
|
||||||
String tplContent = templateFile.getFileContent();
|
|
||||||
Velocity.evaluate(context, sw, "", tplContent);
|
|
||||||
return sw.toString();
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
throw new ServiceException("渲染模板失败,表名:" + tableId);
|
throw new ServiceException("渲染模板失败,表名:" + tableId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
throw new ServiceException("未找到模板文件:" + category);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private GenProject getRequiredProject(Long projectId) {
|
||||||
* 设置代码片段
|
GenProject project = genProjectMapper.selectGenProjectById(projectId);
|
||||||
* @param table
|
if (project == null) {
|
||||||
*/
|
throw new ServiceException("项目不存在");
|
||||||
private void setCodeSnippet(GenTable table) {
|
}
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SysProjectTemplate getRequiredProjectTemplate(GenProject project, String type) {
|
||||||
|
SysProjectTemplate projectTemplate = sysProjectTemplateService.selectSysProjectTemplateByProjectAndType(project.getProjectId(), type);
|
||||||
|
if (projectTemplate == null || projectTemplate.getTemplateId() == null) {
|
||||||
|
throw new ServiceException("项目未配置" + type + "模板");
|
||||||
|
}
|
||||||
|
return projectTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TemplateFile> getRequiredTemplateFiles(Long templateId) {
|
||||||
|
List<TemplateFile> templateFileList = templateFileService.selectTemplateFilesByTemplateId(templateId);
|
||||||
|
if (StringUtils.isEmpty(templateFileList)) {
|
||||||
|
throw new ServiceException("模板未配置文件");
|
||||||
|
}
|
||||||
|
return templateFileList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isTableScopedNode(SysProjectStructure node) {
|
||||||
|
return node.getTableId() != null && node.getTableId() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getNodeKey(Long nodeId, Long tableId) {
|
||||||
|
return tableId == null ? String.valueOf(nodeId) : nodeId + "-" + tableId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> createStructureNodeData(SysProjectStructure node, GenProject project, GenTable table) {
|
||||||
|
Map<String, Object> nodeData = new LinkedHashMap<>();
|
||||||
|
nodeData.put("id", table == null ? node.getNodeId() : getNodeKey(node.getNodeId(), table.getTableId()));
|
||||||
|
nodeData.put("name", replaceNodeName(node.getNodeName(), project, table));
|
||||||
|
nodeData.put("type", node.getNodeType());
|
||||||
|
nodeData.put("category", node.getCategory());
|
||||||
|
nodeData.put("tableId", table == null ? node.getTableId() : table.getTableId());
|
||||||
|
if ("folder".equals(node.getNodeType())) {
|
||||||
|
nodeData.put("children", new ArrayList<>());
|
||||||
|
}
|
||||||
|
return nodeData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String replaceNodeName(String nodeName, GenProject project, GenTable table) {
|
||||||
|
if (nodeName == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String result = nodeName;
|
||||||
|
result = result.replace("{projectName}", StringUtils.defaultString(project.getProjectFileName()));
|
||||||
|
result = result.replace("{packageName}", StringUtils.defaultString(project.getPackageName()));
|
||||||
|
if (table != null) {
|
||||||
|
result = result.replace("{ClassName}", StringUtils.defaultString(table.getClassName()));
|
||||||
|
result = result.replace("{className}", StringUtils.uncapitalize(StringUtils.defaultString(table.getClassName())));
|
||||||
|
result = result.replace("{tableName}", StringUtils.defaultString(table.getTableName()));
|
||||||
|
result = result.replace("{businessName}", StringUtils.defaultString(table.getBusinessName()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addNodeToParent(List<Map<String, Object>> roots, Map<String, Object> nodeData,
|
||||||
|
SysProjectStructure node, Map<String, Map<String, Object>> nodeMap,
|
||||||
|
Map<Long, SysProjectStructure> sourceNodeMap, GenTable table) {
|
||||||
|
if (nodeData == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (node.getParentId() == null || node.getParentId() == 0) {
|
||||||
|
roots.add(nodeData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SysProjectStructure parentSource = sourceNodeMap.get(node.getParentId());
|
||||||
|
Long parentTableId = parentSource != null && isTableScopedNode(parentSource) && table != null ? table.getTableId() : null;
|
||||||
|
Map<String, Object> parentNode = nodeMap.get(getNodeKey(node.getParentId(), parentTableId));
|
||||||
|
if (parentNode == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Map<String, Object>> children = (List<Map<String, Object>>) parentNode.get("children");
|
||||||
|
if (children != null) {
|
||||||
|
children.add(nodeData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean matchesTemplateFile(TemplateFile templateFile, String templateFileName) {
|
||||||
|
if (templateFile == null || StringUtils.isEmpty(templateFileName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return StringUtils.equals(templateFile.getFileName(), templateFileName)
|
||||||
|
|| StringUtils.equals(templateFile.getFilePath(), templateFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String renderTemplate(GenProject project, Long tableId, List<SysProjectModule> modules, TemplateFile templateFile) {
|
||||||
|
VelocityContext context = prepareVelocityContext(project, tableId, modules, templateFile);
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
Velocity.evaluate(context, sw, "", StringUtils.defaultString(templateFile.getFileContent()));
|
||||||
|
return sw.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private VelocityContext prepareVelocityContext(GenProject project, Long tableId, List<SysProjectModule> modules, TemplateFile templateFile) {
|
||||||
|
if (tableId != null && tableId != -1) {
|
||||||
|
GenTable table = getRequiredTable(tableId);
|
||||||
|
table.setModules(modules);
|
||||||
|
table.setPackageName(project.getPackageName());
|
||||||
|
// 设置主子表信息
|
||||||
|
setSubTable(table);
|
||||||
|
// 设置主键列信息
|
||||||
|
setPkColumn(table);
|
||||||
|
VelocityContext context = VelocityUtils.prepareContext(table);
|
||||||
|
putSnippetVariables(context, table, modules, templateFile);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
return VelocityUtils.prepareContextProject(project);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GenTable getRequiredTable(Long tableId) {
|
||||||
|
GenTable table = genTableMapper.selectGenTableById(tableId);
|
||||||
|
if (table == null) {
|
||||||
|
throw new ServiceException("业务表不存在:" + tableId);
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(table.getColumns())) {
|
||||||
|
throw new ServiceException("业务表未配置字段:" + table.getTableName());
|
||||||
|
}
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void putSnippetVariables(VelocityContext context, GenTable table, List<SysProjectModule> modules, TemplateFile templateFile) {
|
||||||
SysCodeSnippet codeSnippet = new SysCodeSnippet();
|
SysCodeSnippet codeSnippet = new SysCodeSnippet();
|
||||||
// codeSnippet.setRelationTableName(table.getTableName());
|
codeSnippet.setStatus("0");
|
||||||
List<SysCodeSnippet> codeSnippetList = codeSnippetService.selectSysCodeSnippetList(codeSnippet);
|
List<SysCodeSnippet> codeSnippetList = codeSnippetService.selectSysCodeSnippetList(codeSnippet);
|
||||||
table.setCodeSnippetList(codeSnippetList);
|
if (StringUtils.isEmpty(codeSnippetList)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, StringBuilder> snippetContentMap = new LinkedHashMap<>();
|
||||||
|
for (SysCodeSnippet snippet : codeSnippetList) {
|
||||||
|
if (StringUtils.isNotEmpty(snippet.getInsertPoint())) {
|
||||||
|
snippetContentMap.putIfAbsent(snippet.getInsertPoint(), new StringBuilder());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (SysCodeSnippet snippet : codeSnippetList) {
|
||||||
|
if (matchesSnippet(snippet, table, modules, templateFile)) {
|
||||||
|
StringBuilder content = snippetContentMap.get(snippet.getInsertPoint());
|
||||||
|
if (content.length() > 0) {
|
||||||
|
content.append(System.lineSeparator());
|
||||||
|
}
|
||||||
|
content.append(snippet.getSnippetContent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, StringBuilder> entry : snippetContentMap.entrySet()) {
|
||||||
|
context.put(entry.getKey(), entry.getValue().toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private boolean matchesSnippet(SysCodeSnippet snippet, GenTable table, List<SysProjectModule> modules, TemplateFile templateFile) {
|
||||||
* 获取包前缀
|
return snippet != null
|
||||||
*
|
&& StringUtils.isNotEmpty(snippet.getInsertPoint())
|
||||||
* @param packageName 包名称
|
&& StringUtils.isNotEmpty(snippet.getSnippetContent())
|
||||||
* @return 包前缀名称
|
&& isSnippetEnabled(snippet)
|
||||||
*/
|
&& matchesSnippetModule(snippet, modules)
|
||||||
private String getPackagePrefix(String packageName) {
|
&& matchesSnippetTable(snippet, table)
|
||||||
int lastIndex = packageName.lastIndexOf(".");
|
&& matchesSnippetTemplate(snippet, templateFile);
|
||||||
return StringUtils.substring(packageName, 0, lastIndex);
|
}
|
||||||
|
|
||||||
|
private boolean isSnippetEnabled(SysCodeSnippet snippet) {
|
||||||
|
return (StringUtils.isEmpty(snippet.getStatus()) || "0".equals(snippet.getStatus()))
|
||||||
|
&& (StringUtils.isEmpty(snippet.getDelFlag()) || "0".equals(snippet.getDelFlag()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean matchesSnippetModule(SysCodeSnippet snippet, List<SysProjectModule> modules) {
|
||||||
|
if (snippet.getModuleId() == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(modules)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (SysProjectModule module : modules) {
|
||||||
|
if (snippet.getModuleId().equals(module.getModuleId())
|
||||||
|
&& (StringUtils.isEmpty(module.getStatus()) || "0".equals(module.getStatus()))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean matchesSnippetTable(SysCodeSnippet snippet, GenTable table) {
|
||||||
|
return StringUtils.isEmpty(snippet.getRelationTableName())
|
||||||
|
|| StringUtils.equals(snippet.getRelationTableName(), table.getTableName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean matchesSnippetTemplate(SysCodeSnippet snippet, TemplateFile templateFile) {
|
||||||
|
return StringUtils.isEmpty(snippet.getTemplateFileName())
|
||||||
|
|| matchesTemplateFile(templateFile, snippet.getTemplateFileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -78,17 +78,44 @@ public class VelocityUtils {
|
|||||||
List<SysProjectModule> modules = genTable.getModules();
|
List<SysProjectModule> modules = genTable.getModules();
|
||||||
if (!Objects.isNull(codeList)) {
|
if (!Objects.isNull(codeList)) {
|
||||||
for (SysCodeSnippet code : codeList) {
|
for (SysCodeSnippet code : codeList) {
|
||||||
if (modules.stream().anyMatch(module -> module.getModuleId().equals(code.getModuleId()))
|
if (StringUtils.isNotEmpty(code.getInsertPoint())) {
|
||||||
&& code.getRelationTableName().equals(genTable.getTableName())) {
|
|
||||||
velocityContext.put(code.getInsertPoint(), code.getSnippetContent());
|
|
||||||
} else {
|
|
||||||
velocityContext.put(code.getInsertPoint(), "");
|
velocityContext.put(code.getInsertPoint(), "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (SysCodeSnippet code : codeList) {
|
||||||
|
if (matchesSnippet(code, modules, genTable)) {
|
||||||
|
String existing = StringUtils.defaultString((String) velocityContext.get(code.getInsertPoint()));
|
||||||
|
String value = StringUtils.isEmpty(existing) ? code.getSnippetContent() : existing + System.lineSeparator() + code.getSnippetContent();
|
||||||
|
velocityContext.put(code.getInsertPoint(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return velocityContext;
|
return velocityContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean matchesSnippet(SysCodeSnippet code, List<SysProjectModule> modules, GenTable genTable) {
|
||||||
|
if (code == null || StringUtils.isEmpty(code.getInsertPoint()) || StringUtils.isEmpty(code.getSnippetContent())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(code.getStatus()) && !"0".equals(code.getStatus())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(code.getDelFlag()) && !"0".equals(code.getDelFlag())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(code.getRelationTableName()) && !code.getRelationTableName().equals(genTable.getTableName())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (code.getModuleId() == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(modules)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return modules.stream().anyMatch(module -> code.getModuleId().equals(module.getModuleId())
|
||||||
|
&& (StringUtils.isEmpty(module.getStatus()) || "0".equals(module.getStatus())));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置模板变量信息
|
* 设置模板变量信息
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,233 @@
|
|||||||
|
package com.ruoyi.generator.service;
|
||||||
|
|
||||||
|
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.TemplateFile;
|
||||||
|
import com.ruoyi.generator.mapper.GenProjectMapper;
|
||||||
|
import com.ruoyi.generator.mapper.GenTableMapper;
|
||||||
|
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.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
public class GenProjectServiceImplTest {
|
||||||
|
private GenProjectServiceImpl service;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private GenProjectMapper genProjectMapper;
|
||||||
|
@Mock
|
||||||
|
private GenTableMapper genTableMapper;
|
||||||
|
@Mock
|
||||||
|
private ITemplateFileService templateFileService;
|
||||||
|
@Mock
|
||||||
|
private ISysCodeSnippetService codeSnippetService;
|
||||||
|
@Mock
|
||||||
|
private ISysProjectModuleService sysProjectModuleService;
|
||||||
|
@Mock
|
||||||
|
private ISysProjectTemplateService sysProjectTemplateService;
|
||||||
|
@Mock
|
||||||
|
private ISysProjectStructureService sysProjectStructureService;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
service = new GenProjectServiceImpl();
|
||||||
|
setField("genProjectMapper", genProjectMapper);
|
||||||
|
setField("genTableMapper", genTableMapper);
|
||||||
|
setField("templateFileService", templateFileService);
|
||||||
|
setField("codeSnippetService", codeSnippetService);
|
||||||
|
setField("sysProjectModuleService", sysProjectModuleService);
|
||||||
|
setField("sysProjectTemplateService", sysProjectTemplateService);
|
||||||
|
setField("sysProjectStructureService", sysProjectStructureService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getProjectStructureAttachesTableScopedChildrenToEachGeneratedTableFolder() {
|
||||||
|
GenProject project = project();
|
||||||
|
GenTable userTable = table(11L, "sys_user", "User");
|
||||||
|
GenTable roleTable = table(12L, "sys_role", "Role");
|
||||||
|
SysProjectTemplate projectTemplate = projectTemplate(100L);
|
||||||
|
|
||||||
|
when(genProjectMapper.selectGenProjectById(1L)).thenReturn(project);
|
||||||
|
when(genTableMapper.selectGenTablesByProjectId(1L)).thenReturn(Arrays.asList(userTable, roleTable));
|
||||||
|
when(sysProjectTemplateService.selectSysProjectTemplateByProjectAndType(1L, "backend")).thenReturn(projectTemplate);
|
||||||
|
when(sysProjectStructureService.selectProjectStructureListByModule(1L, 100L)).thenReturn(Arrays.asList(
|
||||||
|
structure(1L, 0L, "{projectName}", "folder", null, null),
|
||||||
|
structure(2L, 1L, "src", "folder", null, null),
|
||||||
|
structure(3L, 2L, "{ClassName}", "folder", 0L, null),
|
||||||
|
structure(4L, 3L, "{ClassName}Controller.java", "file", 0L, "controller.java.vm")
|
||||||
|
));
|
||||||
|
|
||||||
|
List<Map<String, Object>> structure = service.getProjectStructure(1L, "backend");
|
||||||
|
|
||||||
|
Map<String, Object> root = structure.get(0);
|
||||||
|
assertEquals("demo-app", root.get("name"));
|
||||||
|
Map<String, Object> src = child(root, 0);
|
||||||
|
Map<String, Object> userFolder = child(src, 0);
|
||||||
|
Map<String, Object> roleFolder = child(src, 1);
|
||||||
|
assertEquals("User", userFolder.get("name"));
|
||||||
|
assertEquals("Role", roleFolder.get("name"));
|
||||||
|
assertEquals("UserController.java", child(userFolder, 0).get("name"));
|
||||||
|
assertEquals("RoleController.java", child(roleFolder, 0).get("name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void previewCodeUsesExactTemplateFileNameMatch() {
|
||||||
|
GenProject project = project();
|
||||||
|
GenTable table = table(11L, "sys_user", "User");
|
||||||
|
|
||||||
|
when(genProjectMapper.selectGenProjectById(1L)).thenReturn(project);
|
||||||
|
when(genTableMapper.selectGenTablesByProjectId(1L)).thenReturn(Arrays.asList(table));
|
||||||
|
when(genTableMapper.selectGenTableById(11L)).thenReturn(table);
|
||||||
|
when(sysProjectModuleService.selectSysProjectModuleList(any(SysProjectModule.class))).thenReturn(Arrays.asList(projectModule(1L)));
|
||||||
|
when(codeSnippetService.selectSysCodeSnippetList(any(SysCodeSnippet.class))).thenReturn(Arrays.asList());
|
||||||
|
when(sysProjectTemplateService.selectSysProjectTemplateByProjectAndType(1L, "backend")).thenReturn(projectTemplate(100L));
|
||||||
|
when(templateFileService.selectTemplateFilesByTemplateId(100L)).thenReturn(Arrays.asList(
|
||||||
|
templateFile("controller.java.vm", "controller"),
|
||||||
|
templateFile("my-controller.java.vm", "wrong")
|
||||||
|
));
|
||||||
|
|
||||||
|
Map<String, String> preview = service.previewCode(1L, 11L, "controller.java.vm", "backend");
|
||||||
|
|
||||||
|
assertEquals(1, preview.size());
|
||||||
|
assertTrue(preview.containsKey("controller.java.vm"));
|
||||||
|
assertFalse(preview.containsKey("my-controller.java.vm"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void previewCodeAppliesOnlyMatchingActiveSnippetToTemplateInsertPoint() {
|
||||||
|
GenProject project = project();
|
||||||
|
GenTable table = table(11L, "sys_user", "User");
|
||||||
|
SysCodeSnippet matching = snippet(1L, "sys_user", "controller.java.vm", "controllerExtraMethods", "public void audit() {}");
|
||||||
|
SysCodeSnippet unrelatedTable = snippet(1L, "sys_role", "controller.java.vm", "controllerExtraMethods", "public void wrong() {}");
|
||||||
|
|
||||||
|
when(genProjectMapper.selectGenProjectById(1L)).thenReturn(project);
|
||||||
|
when(genTableMapper.selectGenTablesByProjectId(1L)).thenReturn(Arrays.asList(table));
|
||||||
|
when(genTableMapper.selectGenTableById(11L)).thenReturn(table);
|
||||||
|
when(sysProjectModuleService.selectSysProjectModuleList(any(SysProjectModule.class))).thenReturn(Arrays.asList(projectModule(1L)));
|
||||||
|
when(codeSnippetService.selectSysCodeSnippetList(any(SysCodeSnippet.class))).thenReturn(Arrays.asList(matching, unrelatedTable));
|
||||||
|
when(sysProjectTemplateService.selectSysProjectTemplateByProjectAndType(1L, "backend")).thenReturn(projectTemplate(100L));
|
||||||
|
when(templateFileService.selectTemplateFilesByTemplateId(100L)).thenReturn(Arrays.asList(
|
||||||
|
templateFile("controller.java.vm", "class UserController { $controllerExtraMethods }")
|
||||||
|
));
|
||||||
|
|
||||||
|
Map<String, String> preview = service.previewCode(1L, 11L, "controller.java.vm", "backend");
|
||||||
|
|
||||||
|
String content = preview.get("controller.java.vm");
|
||||||
|
assertTrue(content.contains("public void audit() {}"));
|
||||||
|
assertFalse(content.contains("public void wrong() {}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private Map<String, Object> child(Map<String, Object> node, int index) {
|
||||||
|
return ((List<Map<String, Object>>) node.get("children")).get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setField(String name, Object value) throws Exception {
|
||||||
|
Field field = GenProjectServiceImpl.class.getDeclaredField(name);
|
||||||
|
field.setAccessible(true);
|
||||||
|
field.set(service, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GenProject project() {
|
||||||
|
GenProject project = new GenProject();
|
||||||
|
project.setProjectId(1L);
|
||||||
|
project.setProjectName("Demo");
|
||||||
|
project.setProjectFileName("demo-app");
|
||||||
|
project.setPackageName("com.example.demo");
|
||||||
|
project.setTables(Arrays.asList(table(11L, "sys_user", "User")));
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GenTable table(Long tableId, String tableName, String className) {
|
||||||
|
GenTable table = new GenTable();
|
||||||
|
table.setTableId(tableId);
|
||||||
|
table.setTableName(tableName);
|
||||||
|
table.setTableComment(className);
|
||||||
|
table.setClassName(className);
|
||||||
|
table.setModuleName("system");
|
||||||
|
table.setBusinessName(className.toLowerCase());
|
||||||
|
table.setFunctionName(className);
|
||||||
|
table.setFunctionAuthor("tester");
|
||||||
|
table.setTplCategory("crud");
|
||||||
|
table.setOptions("{}");
|
||||||
|
table.setColumns(Arrays.asList(pkColumn(tableId)));
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GenTableColumn pkColumn(Long tableId) {
|
||||||
|
GenTableColumn column = new GenTableColumn();
|
||||||
|
column.setTableId(tableId);
|
||||||
|
column.setColumnName("id");
|
||||||
|
column.setColumnType("bigint");
|
||||||
|
column.setJavaType("Long");
|
||||||
|
column.setJavaField("id");
|
||||||
|
column.setIsPk("1");
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SysProjectTemplate projectTemplate(Long templateId) {
|
||||||
|
SysProjectTemplate projectTemplate = new SysProjectTemplate();
|
||||||
|
projectTemplate.setProjectId(1L);
|
||||||
|
projectTemplate.setTemplateId(templateId);
|
||||||
|
projectTemplate.setTemplateType("backend");
|
||||||
|
return projectTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SysProjectModule projectModule(Long moduleId) {
|
||||||
|
SysProjectModule module = new SysProjectModule();
|
||||||
|
module.setProjectId(1L);
|
||||||
|
module.setModuleId(moduleId);
|
||||||
|
module.setStatus("0");
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SysProjectStructure structure(Long nodeId, Long parentId, String name, String type, Long tableId, String category) {
|
||||||
|
SysProjectStructure structure = new SysProjectStructure();
|
||||||
|
structure.setNodeId(nodeId);
|
||||||
|
structure.setParentId(parentId);
|
||||||
|
structure.setNodeName(name);
|
||||||
|
structure.setNodeType(type);
|
||||||
|
structure.setTemplateId(100L);
|
||||||
|
structure.setTableId(tableId);
|
||||||
|
structure.setCategory(category);
|
||||||
|
structure.setStatus("0");
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TemplateFile templateFile(String fileName, String fileContent) {
|
||||||
|
TemplateFile templateFile = new TemplateFile();
|
||||||
|
templateFile.setTemplateId(100L);
|
||||||
|
templateFile.setFileName(fileName);
|
||||||
|
templateFile.setFileContent(fileContent);
|
||||||
|
return templateFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SysCodeSnippet snippet(Long moduleId, String relationTableName, String templateFileName, String insertPoint, String content) {
|
||||||
|
SysCodeSnippet snippet = new SysCodeSnippet();
|
||||||
|
snippet.setModuleId(moduleId);
|
||||||
|
snippet.setRelationTableName(relationTableName);
|
||||||
|
snippet.setTemplateFileName(templateFileName);
|
||||||
|
snippet.setInsertPoint(insertPoint);
|
||||||
|
snippet.setSnippetContent(content);
|
||||||
|
snippet.setStatus("0");
|
||||||
|
snippet.setDelFlag("0");
|
||||||
|
return snippet;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
icon="el-icon-plus"
|
icon="el-icon-plus"
|
||||||
size="mini"
|
size="mini"
|
||||||
@click="handleAdd"
|
@click="handleAdd"
|
||||||
v-hasPermi="['system:project:add']"
|
v-hasPermi="['generator:project:add']"
|
||||||
>新增</el-button>
|
>新增</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
size="mini"
|
size="mini"
|
||||||
:disabled="single"
|
:disabled="single"
|
||||||
@click="handleUpdate"
|
@click="handleUpdate"
|
||||||
v-hasPermi="['system:project:edit']"
|
v-hasPermi="['generator:project:edit']"
|
||||||
>修改</el-button>
|
>修改</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
size="mini"
|
size="mini"
|
||||||
:disabled="multiple"
|
:disabled="multiple"
|
||||||
@click="handleDelete"
|
@click="handleDelete"
|
||||||
v-hasPermi="['system:project:remove']"
|
v-hasPermi="['generator:project:remove']"
|
||||||
>删除</el-button>
|
>删除</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
icon="el-icon-download"
|
icon="el-icon-download"
|
||||||
size="mini"
|
size="mini"
|
||||||
@click="handleExport"
|
@click="handleExport"
|
||||||
v-hasPermi="['system:project:export']"
|
v-hasPermi="['generator:project:export']"
|
||||||
>导出</el-button>
|
>导出</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
@@ -117,7 +117,7 @@
|
|||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-notebook-2"
|
icon="el-icon-notebook-2"
|
||||||
@click="handleTableConfig(scope.row)"
|
@click="handleTableConfig(scope.row)"
|
||||||
v-hasPermi="['generator:table:list']"
|
v-hasPermi="['system:projectTable:list']"
|
||||||
>数据表配置</el-button>
|
>数据表配置</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -128,7 +128,7 @@
|
|||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-files"
|
icon="el-icon-files"
|
||||||
@click="handleTemplateConfig(scope.row)"
|
@click="handleTemplateConfig(scope.row)"
|
||||||
v-hasPermi="['generator:template:config']"
|
v-hasPermi="['generator:template:list']"
|
||||||
>代码模板配置</el-button>
|
>代码模板配置</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -144,35 +144,35 @@
|
|||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-view"
|
icon="el-icon-view"
|
||||||
@click="handlePreview(scope.row)"
|
@click="handlePreview(scope.row)"
|
||||||
v-hasPermi="['system:project:preview']"
|
v-hasPermi="['generator:project:preview']"
|
||||||
>预览后端项目</el-button>
|
>预览后端项目</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-view"
|
icon="el-icon-view"
|
||||||
@click="handlePreviewAdmin(scope.row)"
|
@click="handlePreviewAdmin(scope.row)"
|
||||||
v-hasPermi="['system:project:preview']"
|
v-hasPermi="['generator:project:preview']"
|
||||||
>预览后台前端项目</el-button>
|
>预览后台前端项目</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-view"
|
icon="el-icon-view"
|
||||||
@click="handlePreviewFront(scope.row)"
|
@click="handlePreviewFront(scope.row)"
|
||||||
v-hasPermi="['system:project:preview']"
|
v-hasPermi="['generator:project:preview']"
|
||||||
>预览前台前端项目</el-button>
|
>预览前台前端项目</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-edit"
|
icon="el-icon-edit"
|
||||||
@click="handleUpdate(scope.row)"
|
@click="handleUpdate(scope.row)"
|
||||||
v-hasPermi="['system:project:edit']"
|
v-hasPermi="['generator:project:edit']"
|
||||||
>修改</el-button>
|
>修改</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-delete"
|
icon="el-icon-delete"
|
||||||
@click="handleDelete(scope.row)"
|
@click="handleDelete(scope.row)"
|
||||||
v-hasPermi="['system:project:remove']"
|
v-hasPermi="['generator:project:remove']"
|
||||||
>删除</el-button>
|
>删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -406,7 +406,7 @@ export default {
|
|||||||
},
|
},
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
handleExport() {
|
handleExport() {
|
||||||
this.download('system/project/export', {
|
this.download('generator/project/export', {
|
||||||
...this.queryParams
|
...this.queryParams
|
||||||
}, `project_${new Date().getTime()}.xlsx`)
|
}, `project_${new Date().getTime()}.xlsx`)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -41,7 +41,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
<el-button @click="handleBack">返 回</el-button>
|
<el-button @click="handleBack">返 回</el-button>
|
||||||
<el-button type="primary" @click="handleDownload">下 载</el-button>
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleDownload"
|
||||||
|
v-hasPermi="['generator:project:download']"
|
||||||
|
>下 载</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
@@ -138,7 +142,6 @@ export default {
|
|||||||
language = 'sql'
|
language = 'sql'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const result = hljs.highlight(language, code || '', true)
|
const result = hljs.highlight(language, code || '', true)
|
||||||
return result.value || ' '
|
return result.value || ' '
|
||||||
},
|
},
|
||||||
|
|||||||
1240
RuoYi-Vue/sql/db.sql
Normal file
1240
RuoYi-Vue/sql/db.sql
Normal file
File diff suppressed because it is too large
Load Diff
379
RuoYi-Vue/sql/generator_test_data.sql
Normal file
379
RuoYi-Vue/sql/generator_test_data.sql
Normal file
@@ -0,0 +1,379 @@
|
|||||||
|
-- =================================================
|
||||||
|
-- 代码生成平台测试数据
|
||||||
|
-- 使用方式:
|
||||||
|
-- 1. 先导入 sql/db.sql
|
||||||
|
-- 2. 再导入本文件:mysql -uroot -p ry < sql/generator_test_data.sql
|
||||||
|
-- 3. 登录 admin/admin123,进入「代码生成平台 -> 项目管理」
|
||||||
|
-- 4. 打开「演示生成项目」,可直接预览/下载 backend、admin_frontend、frontend 三类项目
|
||||||
|
-- =================================================
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
-- 清理同一批测试数据,方便重复导入
|
||||||
|
DELETE FROM sys_project_structure WHERE template_id IN (9001, 9002, 9003) OR node_id BETWEEN 900100 AND 900399;
|
||||||
|
DELETE FROM sys_code_snippet_module WHERE snippet_id BETWEEN 9001 AND 9099;
|
||||||
|
DELETE FROM sys_code_snippet WHERE snippet_id BETWEEN 9001 AND 9099;
|
||||||
|
DELETE FROM sys_project_template WHERE project_id = 9001 OR template_id IN (9001, 9002, 9003);
|
||||||
|
DELETE FROM sys_project_table WHERE project_id = 9001 OR table_id = 9001;
|
||||||
|
DELETE FROM gen_table_project_rel WHERE project_id = 9001 OR table_id = 9001;
|
||||||
|
DELETE FROM sys_project_module WHERE project_id = 9001 OR module_id = 9001;
|
||||||
|
DELETE FROM sys_template_file WHERE template_id IN (9001, 9002, 9003) OR template_file_id BETWEEN 900100 AND 900399;
|
||||||
|
DELETE FROM sys_template WHERE template_id IN (9001, 9002, 9003);
|
||||||
|
DELETE FROM gen_table_column WHERE table_id = 9001 OR column_id BETWEEN 900100 AND 900199;
|
||||||
|
DELETE FROM gen_table WHERE table_id = 9001;
|
||||||
|
DELETE FROM gen_project WHERE project_id = 9001;
|
||||||
|
DELETE FROM sys_module WHERE module_id = 9001;
|
||||||
|
DROP TABLE IF EXISTS demo_product;
|
||||||
|
|
||||||
|
-- 示例业务表:不是生成逻辑必须项,但方便和 gen_table 元数据对照
|
||||||
|
CREATE TABLE demo_product (
|
||||||
|
product_id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '商品ID',
|
||||||
|
product_name varchar(100) NOT NULL COMMENT '商品名称',
|
||||||
|
product_code varchar(64) NOT NULL COMMENT '商品编码',
|
||||||
|
price decimal(10,2) DEFAULT 0.00 COMMENT '商品价格',
|
||||||
|
status char(1) DEFAULT '0' COMMENT '状态',
|
||||||
|
create_time datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
|
remark varchar(500) DEFAULT NULL COMMENT '备注',
|
||||||
|
PRIMARY KEY (product_id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='演示商品表';
|
||||||
|
|
||||||
|
INSERT INTO demo_product (product_id, product_name, product_code, price, status, create_time, remark) VALUES
|
||||||
|
(1, '测试商品A', 'DEMO-A', 19.90, '0', sysdate(), '用于代码生成预览'),
|
||||||
|
(2, '测试商品B', 'DEMO-B', 29.90, '0', sysdate(), '用于代码生成下载');
|
||||||
|
|
||||||
|
-- 测试项目
|
||||||
|
INSERT INTO gen_project (project_id, project_name, project_file_name, package_name, version, project_desc, author, front_framework, back_framework, status, create_by, create_time, remark) VALUES
|
||||||
|
(9001, '演示生成项目', 'demo-generated-app', 'com.example.demo', '1.0.0', '代码生成平台测试项目,可直接预览和下载生成结果', 'Codex', 'Vue2 + Element UI', 'Spring Boot + MyBatis', '0', 'admin', sysdate(), '测试数据,可重复导入');
|
||||||
|
|
||||||
|
-- 测试功能模块,用于验证代码片段按项目模块生效
|
||||||
|
INSERT INTO sys_module (module_id, module_name, module_alias, module_desc, status, del_flag, create_by, create_time, remark) VALUES
|
||||||
|
(9001, '审计增强', 'audit', '演示代码片段模块,给 Controller 注入 ping 方法', '0', '0', 'admin', sysdate(), '测试数据');
|
||||||
|
|
||||||
|
INSERT INTO sys_project_module (id, project_id, module_id, status, create_by, create_time, remark) VALUES
|
||||||
|
(9001, 9001, 9001, '0', 'admin', sysdate(), '演示项目启用审计增强模块');
|
||||||
|
|
||||||
|
-- 示例生成表元数据
|
||||||
|
INSERT INTO gen_table (table_id, table_name, table_comment, class_name, tpl_category, tpl_web_type, package_name, module_name, business_name, function_name, function_author, gen_type, gen_path, options, create_by, create_time, remark, create_table_sql) VALUES
|
||||||
|
(9001, 'demo_product', '演示商品', 'DemoProduct', 'crud', 'element-ui', 'com.example.demo', 'demo', 'product', '演示商品', 'Codex', '0', '/', '{"parentMenuId":"3"}', 'admin', sysdate(), '测试数据',
|
||||||
|
'CREATE TABLE `demo_product` (
|
||||||
|
`product_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT ''商品ID'',
|
||||||
|
`product_name` varchar(100) NOT NULL COMMENT ''商品名称'',
|
||||||
|
`product_code` varchar(64) NOT NULL COMMENT ''商品编码'',
|
||||||
|
`price` decimal(10,2) DEFAULT 0.00 COMMENT ''商品价格'',
|
||||||
|
`status` char(1) DEFAULT ''0'' COMMENT ''状态'',
|
||||||
|
`create_time` datetime DEFAULT NULL COMMENT ''创建时间'',
|
||||||
|
`remark` varchar(500) DEFAULT NULL COMMENT ''备注'',
|
||||||
|
PRIMARY KEY (`product_id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=''演示商品表'';');
|
||||||
|
|
||||||
|
INSERT INTO gen_table_column (column_id, table_id, column_name, column_comment, column_type, java_type, java_field, is_pk, is_increment, is_required, is_insert, is_edit, is_list, is_query, query_type, html_type, dict_type, sort, create_by, create_time) VALUES
|
||||||
|
(900101, 9001, 'product_id', '商品ID', 'bigint(20)', 'Long', 'productId', '1', '1', '1', '0', '0', '0', '0', 'EQ', 'input', '', 1, 'admin', sysdate()),
|
||||||
|
(900102, 9001, 'product_name', '商品名称', 'varchar(100)', 'String', 'productName', '0', '0', '1', '1', '1', '1', '1', 'LIKE', 'input', '', 2, 'admin', sysdate()),
|
||||||
|
(900103, 9001, 'product_code', '商品编码', 'varchar(64)', 'String', 'productCode', '0', '0', '1', '1', '1', '1', '1', 'LIKE', 'input', '', 3, 'admin', sysdate()),
|
||||||
|
(900104, 9001, 'price', '商品价格', 'decimal(10,2)', 'BigDecimal', 'price', '0', '0', '0', '1', '1', '1', '0', 'EQ', 'input', '', 4, 'admin', sysdate()),
|
||||||
|
(900105, 9001, 'status', '状态', 'char(1)', 'String', 'status', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'select', 'sys_normal_disable', 5, 'admin', sysdate()),
|
||||||
|
(900106, 9001, 'create_time', '创建时间', 'datetime', 'Date', 'createTime', '0', '0', '0', '0', '0', '1', '1', 'BETWEEN', 'datetime', '', 6, 'admin', sysdate()),
|
||||||
|
(900107, 9001, 'remark', '备注', 'varchar(500)', 'String', 'remark', '0', '0', '0', '1', '1', '0', '0', 'EQ', 'textarea', '', 7, 'admin', sysdate());
|
||||||
|
|
||||||
|
INSERT INTO sys_project_table (id, table_id, project_id) VALUES
|
||||||
|
(9001, 9001, 9001);
|
||||||
|
|
||||||
|
INSERT INTO gen_table_project_rel (id, table_id, project_id) VALUES
|
||||||
|
(9001, 9001, 9001);
|
||||||
|
|
||||||
|
-- 三类模板
|
||||||
|
INSERT INTO sys_template (template_id, template_name, template_path, template_desc, template_type, template_status, create_by, create_time, remark) VALUES
|
||||||
|
(9001, '测试后端模板', '/test/backend', '生成 Spring Boot + MyBatis 后端项目骨架', 'backend', 0, 'admin', sysdate(), '测试模板'),
|
||||||
|
(9002, '测试后台前端模板', '/test/admin_frontend', '生成后台前端 API 和列表页骨架', 'admin_frontend', 0, 'admin', sysdate(), '测试模板'),
|
||||||
|
(9003, '测试前台前端模板', '/test/frontend', '生成最小前台前端项目骨架', 'frontend', 0, 'admin', sysdate(), '测试模板');
|
||||||
|
|
||||||
|
INSERT INTO sys_project_template (id, project_id, template_id, template_type) VALUES
|
||||||
|
(9001, 9001, 9001, 'backend'),
|
||||||
|
(9002, 9001, 9002, 'admin_frontend'),
|
||||||
|
(9003, 9001, 9003, 'frontend');
|
||||||
|
|
||||||
|
-- 后端模板文件
|
||||||
|
INSERT INTO sys_template_file (template_file_id, template_id, file_name, module_id, file_path, file_content, create_by, create_time) VALUES
|
||||||
|
(900101, 9001, 'pom.xml.vm', NULL, 'pom.xml.vm',
|
||||||
|
'<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>${packageName}</groupId>
|
||||||
|
<artifactId>${projectFileName}</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<name>${projectName}</name>
|
||||||
|
</project>
|
||||||
|
', 'admin', sysdate()),
|
||||||
|
(900102, 9001, 'application.yml.vm', NULL, 'application.yml.vm',
|
||||||
|
'server:
|
||||||
|
port: 8080
|
||||||
|
spring:
|
||||||
|
application:
|
||||||
|
name: ${projectFileName}
|
||||||
|
', 'admin', sysdate()),
|
||||||
|
(900103, 9001, 'README.md.vm', NULL, 'README.md.vm',
|
||||||
|
'# ${projectName}
|
||||||
|
|
||||||
|
包名:`${packageName}`
|
||||||
|
|
||||||
|
## 建表 SQL
|
||||||
|
|
||||||
|
```sql
|
||||||
|
${createTableSql}
|
||||||
|
```
|
||||||
|
', 'admin', sysdate()),
|
||||||
|
(900104, 9001, 'entity.java.vm', NULL, 'entity.java.vm',
|
||||||
|
'package ${packageName}.domain;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ${functionName}实体
|
||||||
|
*/
|
||||||
|
public class ${ClassName} {
|
||||||
|
#foreach($column in $columns)
|
||||||
|
/** ${column.columnComment} */
|
||||||
|
private ${column.javaType} ${column.javaField};
|
||||||
|
|
||||||
|
#end
|
||||||
|
#foreach($column in $columns)
|
||||||
|
public ${column.javaType} get${column.capJavaField}() {
|
||||||
|
return ${column.javaField};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set${column.capJavaField}(${column.javaType} ${column.javaField}) {
|
||||||
|
this.${column.javaField} = ${column.javaField};
|
||||||
|
}
|
||||||
|
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
', 'admin', sysdate()),
|
||||||
|
(900105, 9001, 'mapper.java.vm', NULL, 'mapper.java.vm',
|
||||||
|
'package ${packageName}.mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import ${packageName}.domain.${ClassName};
|
||||||
|
|
||||||
|
public interface ${ClassName}Mapper {
|
||||||
|
List<${ClassName}> select${ClassName}List(${ClassName} ${className});
|
||||||
|
}
|
||||||
|
', 'admin', sysdate()),
|
||||||
|
(900106, 9001, 'service.java.vm', NULL, 'service.java.vm',
|
||||||
|
'package ${packageName}.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import ${packageName}.domain.${ClassName};
|
||||||
|
|
||||||
|
public interface I${ClassName}Service {
|
||||||
|
List<${ClassName}> select${ClassName}List(${ClassName} ${className});
|
||||||
|
}
|
||||||
|
', 'admin', sysdate()),
|
||||||
|
(900107, 9001, 'serviceImpl.java.vm', NULL, 'serviceImpl.java.vm',
|
||||||
|
'package ${packageName}.service.impl;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import ${packageName}.domain.${ClassName};
|
||||||
|
import ${packageName}.mapper.${ClassName}Mapper;
|
||||||
|
import ${packageName}.service.I${ClassName}Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ${ClassName}ServiceImpl implements I${ClassName}Service {
|
||||||
|
@Resource
|
||||||
|
private ${ClassName}Mapper ${className}Mapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<${ClassName}> select${ClassName}List(${ClassName} ${className}) {
|
||||||
|
return ${className}Mapper.select${ClassName}List(${className});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
', 'admin', sysdate()),
|
||||||
|
(900108, 9001, 'controller.java.vm', NULL, 'controller.java.vm',
|
||||||
|
'package ${packageName}.controller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import ${packageName}.domain.${ClassName};
|
||||||
|
import ${packageName}.service.I${ClassName}Service;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/${moduleName}/${businessName}")
|
||||||
|
public class ${ClassName}Controller {
|
||||||
|
@Resource
|
||||||
|
private I${ClassName}Service ${className}Service;
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
public List<${ClassName}> list(${ClassName} query) {
|
||||||
|
return ${className}Service.select${ClassName}List(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
$!controllerExtraMethods
|
||||||
|
}
|
||||||
|
', 'admin', sysdate()),
|
||||||
|
(900109, 9001, 'mapper.xml.vm', NULL, 'mapper.xml.vm',
|
||||||
|
'<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="${packageName}.mapper.${ClassName}Mapper">
|
||||||
|
<select id="select${ClassName}List" resultType="${packageName}.domain.${ClassName}">
|
||||||
|
select
|
||||||
|
#foreach($column in $columns)
|
||||||
|
${column.columnName}#if($foreach.hasNext),#end
|
||||||
|
#end
|
||||||
|
from ${tableName}
|
||||||
|
</select>
|
||||||
|
</mapper>
|
||||||
|
', 'admin', sysdate());
|
||||||
|
|
||||||
|
-- 后台前端模板文件
|
||||||
|
INSERT INTO sys_template_file (template_file_id, template_id, file_name, module_id, file_path, file_content, create_by, create_time) VALUES
|
||||||
|
(900201, 9002, 'package.json.vm', NULL, 'package.json.vm',
|
||||||
|
'{
|
||||||
|
"name": "${projectFileName}-admin",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vue-cli-service serve"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
', 'admin', sysdate()),
|
||||||
|
(900202, 9002, 'api.js.vm', NULL, 'api.js.vm',
|
||||||
|
'import request from "@/utils/request"
|
||||||
|
|
||||||
|
export function list${ClassName}(query) {
|
||||||
|
return request({
|
||||||
|
url: "/${moduleName}/${businessName}/list",
|
||||||
|
method: "get",
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
', 'admin', sysdate()),
|
||||||
|
(900203, 9002, 'index.vue.vm', NULL, 'index.vue.vm',
|
||||||
|
'<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-table :data="list">
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if($column.isList == "1")
|
||||||
|
<el-table-column label="${column.columnComment}" prop="${column.javaField}" />
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { list${ClassName} } from "@/api/${moduleName}/${businessName}"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "${ClassName}",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
list: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
list${ClassName}({}).then(res => {
|
||||||
|
this.list = res.rows || res.data || []
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
', 'admin', sysdate());
|
||||||
|
|
||||||
|
-- 前台前端模板文件
|
||||||
|
INSERT INTO sys_template_file (template_file_id, template_id, file_name, module_id, file_path, file_content, create_by, create_time) VALUES
|
||||||
|
(900301, 9003, 'package.json.vm', NULL, 'package.json.vm',
|
||||||
|
'{
|
||||||
|
"name": "${projectFileName}-web",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite --host 0.0.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
', 'admin', sysdate()),
|
||||||
|
(900302, 9003, 'README.md.vm', NULL, 'README.md.vm',
|
||||||
|
'# ${projectName} 前台演示
|
||||||
|
|
||||||
|
这是代码生成平台的 frontend 类型测试模板。
|
||||||
|
', 'admin', sysdate()),
|
||||||
|
(900303, 9003, 'index.html.vm', NULL, 'index.html.vm',
|
||||||
|
'<!doctype html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>${projectName}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main id="app">
|
||||||
|
<h1>${projectName}</h1>
|
||||||
|
<p>Generated by RuoYi-Vue code generator.</p>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
', 'admin', sysdate());
|
||||||
|
|
||||||
|
-- 代码片段:只对 demo_product + controller.java.vm 生效
|
||||||
|
INSERT INTO sys_code_snippet (snippet_id, module_id, snippet_content, insert_point, template_file_name, relation_table_name, status, del_flag, create_by, create_time, remark) VALUES
|
||||||
|
(9001, 9001,
|
||||||
|
' @GetMapping("/ping")
|
||||||
|
public String ping() {
|
||||||
|
return "demo-product-ok";
|
||||||
|
}',
|
||||||
|
'controllerExtraMethods', 'controller.java.vm', 'demo_product', '0', '0', 'admin', sysdate(), '演示 Controller 插入点');
|
||||||
|
|
||||||
|
INSERT INTO sys_code_snippet_module (snippet_id, module_id) VALUES
|
||||||
|
(9001, 9001);
|
||||||
|
|
||||||
|
-- 后端项目结构
|
||||||
|
INSERT INTO sys_project_structure (node_id, parent_id, node_name, node_type, module, template_id, table_id, category, sort_order, status, create_by, create_time, update_by, update_time) VALUES
|
||||||
|
(900100, 0, '{projectName}', 'folder', NULL, 9001, NULL, NULL, 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900101, 900100, 'pom.xml', 'file', NULL, 9001, -1, 'pom.xml.vm', 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900102, 900100, 'README.md', 'file', NULL, 9001, -1, 'README.md.vm', 2, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900103, 900100, 'src', 'folder', NULL, 9001, NULL, NULL, 3, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900104, 900103, 'main', 'folder', NULL, 9001, NULL, NULL, 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900105, 900104, 'java', 'folder', NULL, 9001, NULL, NULL, 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900106, 900105, 'com', 'folder', NULL, 9001, NULL, NULL, 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900107, 900106, 'example', 'folder', NULL, 9001, NULL, NULL, 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900108, 900107, 'demo', 'folder', NULL, 9001, NULL, NULL, 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900109, 900108, 'domain', 'folder', NULL, 9001, NULL, NULL, 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900110, 900108, 'mapper', 'folder', NULL, 9001, NULL, NULL, 2, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900111, 900108, 'service', 'folder', NULL, 9001, NULL, NULL, 3, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900112, 900111, 'impl', 'folder', NULL, 9001, NULL, NULL, 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900113, 900108, 'controller', 'folder', NULL, 9001, NULL, NULL, 4, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900114, 900104, 'resources', 'folder', NULL, 9001, NULL, NULL, 2, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900115, 900114, 'mapper', 'folder', NULL, 9001, NULL, NULL, 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900116, 900114, 'application.yml', 'file', NULL, 9001, -1, 'application.yml.vm', 2, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900117, 900109, '{ClassName}.java', 'file', NULL, 9001, 0, 'entity.java.vm', 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900118, 900110, '{ClassName}Mapper.java', 'file', NULL, 9001, 0, 'mapper.java.vm', 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900119, 900111, 'I{ClassName}Service.java', 'file', NULL, 9001, 0, 'service.java.vm', 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900120, 900112, '{ClassName}ServiceImpl.java', 'file', NULL, 9001, 0, 'serviceImpl.java.vm', 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900121, 900113, '{ClassName}Controller.java', 'file', NULL, 9001, 0, 'controller.java.vm', 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900122, 900115, '{ClassName}Mapper.xml', 'file', NULL, 9001, 0, 'mapper.xml.vm', 1, '0', 'admin', sysdate(), '', NULL);
|
||||||
|
|
||||||
|
-- 后台前端项目结构
|
||||||
|
INSERT INTO sys_project_structure (node_id, parent_id, node_name, node_type, module, template_id, table_id, category, sort_order, status, create_by, create_time, update_by, update_time) VALUES
|
||||||
|
(900200, 0, '{projectName}-admin', 'folder', NULL, 9002, NULL, NULL, 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900201, 900200, 'package.json', 'file', NULL, 9002, -1, 'package.json.vm', 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900202, 900200, 'src', 'folder', NULL, 9002, NULL, NULL, 2, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900203, 900202, 'api', 'folder', NULL, 9002, NULL, NULL, 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900204, 900203, 'demo', 'folder', NULL, 9002, NULL, NULL, 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900205, 900202, 'views', 'folder', NULL, 9002, NULL, NULL, 2, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900206, 900205, 'demo', 'folder', NULL, 9002, NULL, NULL, 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900207, 900206, '{businessName}', 'folder', NULL, 9002, 0, NULL, 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900208, 900204, '{businessName}.js', 'file', NULL, 9002, 0, 'api.js.vm', 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900209, 900207, 'index.vue', 'file', NULL, 9002, 0, 'index.vue.vm', 1, '0', 'admin', sysdate(), '', NULL);
|
||||||
|
|
||||||
|
-- 前台前端项目结构
|
||||||
|
INSERT INTO sys_project_structure (node_id, parent_id, node_name, node_type, module, template_id, table_id, category, sort_order, status, create_by, create_time, update_by, update_time) VALUES
|
||||||
|
(900300, 0, '{projectName}-web', 'folder', NULL, 9003, NULL, NULL, 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900301, 900300, 'package.json', 'file', NULL, 9003, -1, 'package.json.vm', 1, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900302, 900300, 'README.md', 'file', NULL, 9003, -1, 'README.md.vm', 2, '0', 'admin', sysdate(), '', NULL),
|
||||||
|
(900303, 900300, 'index.html', 'file', NULL, 9003, -1, 'index.html.vm', 3, '0', 'admin', sysdate(), '', NULL);
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
Reference in New Issue
Block a user