--- name: jeecg-codegen description: "Use when user asks to generate JeecgBoot CRUD code, create a new module, add/modify fields on existing module, or says \"代码生成\", \"生成代码\", \"创建模块\", \"新增功能\", \"建表\", \"加字段\", \"加一个字段\", \"增加字段\", \"新增字段\", \"修改字段\", \"删除字段\", \"generate code\", \"new entity\", \"add field\"" --- # JeecgBoot 代码生成器 将自然语言需求转换为 JeecgBoot 全套 CRUD 代码(后端 Java + 前端 Vue3 + 菜单权限 SQL),并支持对已生成模块的增量字段修改。 ## 交互流程 ### Step 0: 判断操作类型 — 全量生成 or 增量修改? **识别增量修改的关键词:** "加字段"、"增加字段"、"新增字段"、"加一个XX字段"、"删除字段"、"修改字段"、"改一下XX"、"给XX模块加"、"给XX表加" 如果是增量修改 → 进入 **场景C** 如果是全量生成 → 进入 **场景A** 或 **场景B** ### Step 1: 全量生成 — 判断场景 **场景A — 已有表(用户给了表名):** 1. 通过数据库查询获取精确 DDL(见"数据库连接"章节) 2. 从 DDL 中解析:主键类型、全部字段(名称/类型/注释/是否nullable)、是否有系统字段 3. 根据字段类型和注释自动推导前端控件类型 4. 用户无需描述字段,AI 全部自动推导 **场景B — 新建表(用户用自然语言描述需求):** 1. 从用户描述中提取:表名、实体名、功能描述、字段列表 2. 用"智能字段推导"规则推导 DB 类型和前端控件 3. 默认添加全部系统字段(create_by/create_time/update_by/update_time/sys_org_code) 4. 生成建表 DDL 写入 Flyway SQL **场景C — 增量修改(给已有模块加/改/删字段):** 1. **定位目标模块**:从用户提到的表名、模块名、实体名中识别目标 2. **扫描已有代码文件**:在后端和前端目录中搜索已生成的文件 ```bash # 搜索后端 Entity 文件 find {后端项目根目录} -name "{EntityName}.java" -path "*/entity/*" # 搜索前端 data.ts 文件 find {前端项目根目录}/src/views -name "{EntityName}.data.ts" ``` 3. **读取全部已有文件**:Entity.java、*.data.ts、*List.vue、*Modal.vue(如有 Form.vue 也读取) 4. **解析当前字段列表**:从 Entity.java 解析已有字段 5. **推导新字段属性**:用"智能字段推导"规则推导 DB 类型、Java 类型、前端控件 6. **展示修改摘要**,等待用户确认后再修改 **增量修改的操作类型:** - **加字段**:在所有文件中追加新字段定义 - **删字段**:从所有文件中移除指定字段定义 - **改字段**:修改指定字段的类型、控件、注释等 **判断表类型:** - 提到"分类/层级/树/上下级" → **树表** - 提到"主子表/明细/一对多/订单+商品" → **一对多** - 默认 → **单表** ### Step 2: 询问用户选项(仅全量生成需要) 一次性展示所有选项及默认值,用户说"确认"即可全部采用默认值,或只说需要改的: 1. **后端模块**:默认 `jeecg-module-system/jeecg-system-biz` 2. **前端风格**:默认 `vue3`(封装风格),可选 `vue3Native`(原生风格) 3. **前端视图目录**:默认用 entityPackage 值 4. **是否读取系统字典**:默认 `是`,读取后可自动为字段匹配已有字典编码(见"字典智能匹配"章节) ### Step 3: 展示摘要 - **全量生成**:列出表名、字段清单(名称/类型/控件/校验/字典),等待用户确认后再生成。 - **增量修改**:列出要修改的文件路径 + 每个文件的具体变更内容(新增/删除/修改哪些行),等待用户确认。 ### Step 4: 执行 - **全量生成**:读取 `codegen-reference.md` 获取完整模板模式,按顺序生成全部文件。 - **增量修改**:使用 Edit 工具精确修改每个文件,读取 `codegen-reference.md` 的 Section F 获取增量修改模板。 ### Step 5: 输出清单 列出所有生成/修改的文件路径 + 后续操作说明(执行SQL、重启后端等)。 ### 本地环境自动执行菜单 SQL 规则 **判断条件:** 数据库连接地址为 `127.0.0.1` 或 `localhost`(即本地开发环境)。 **自动执行方式:** 生成 Flyway SQL 文件后,同时通过 Bash 工具直接执行菜单权限 SQL: ```bash # 先检查菜单是否已存在,避免重复插入 mysql -h127.0.0.1 -P3306 -uroot -proot jeecgboot3 -e "SELECT id FROM sys_permission WHERE id='{timestamp}01'" # 不存在则执行全部菜单 + 角色授权 SQL mysql -h127.0.0.1 -P3306 -uroot -proot jeecgboot3 < {flyway_sql_file_path} ``` **注意事项:** - 仅在本地环境(127.0.0.1/localhost)自动执行,远程环境只生成 Flyway 文件 - 执行前先检查主菜单 ID 是否已存在,避免重复插入 - 如果 MySQL 执行失败,提示用户手动执行 Flyway SQL,不中断整体流程 - 输出结果中标注 `菜单 SQL:已自动执行 ✓` ## 数据库连接 **已有表场景必须先查数据库!** 通过以下方式获取精确 DDL: ```bash # 读取项目数据库配置 # 配置文件: jeecg-boot-framework-2026/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml # 默认连接: mysql -h127.0.0.1 -P3306 -uroot -proot jeecgboot3 # 查询表 DDL mysql -h127.0.0.1 -P3306 -uroot -proot jeecgboot3 -e "SHOW CREATE TABLE 表名\G" # 查询字段注释 mysql -h127.0.0.1 -P3306 -uroot -proot jeecgboot3 -e "SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, COLUMN_COMMENT, COLUMN_KEY, EXTRA FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='jeecgboot3' AND TABLE_NAME='表名' ORDER BY ORDINAL_POSITION" ``` 如果无法连接数据库,回退方案:在项目 SQL 文件中搜索表定义(`grep -r "CREATE TABLE.*表名"` 在 docs/db/ 目录下)。 ## Flyway 版本号规则 **生成 Flyway SQL 前必须检查已有版本号,自动递增避免冲突!** ```bash # Flyway SQL 目录 ls {后端项目根目录}/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/ | sort -V | tail -5 ``` 版本命名规则:`V{YYYYMMDD}_{序号}__{描述}.sql` - 检查当天是否已有文件(如 `V20260311_1__xxx.sql`) - 如果有,序号递增(`V20260311_2__xxx.sql`) - 如果没有,从 `_1` 开始 ## 菜单 SQL 的 ID 生成 **必须使用真实时间戳确保唯一性!** 通过以下命令获取: ```bash date +%s%3N # 输出13位毫秒级时间戳,如 1741704000123 ``` 用这个时间戳作为基础 ID,依次拼接 01-14: - 主菜单: `{timestamp}01` - 添加按钮: `{timestamp}02` - 编辑按钮: `{timestamp}03` - ... 以此类推 ## 字典智能匹配 **用户选择"读取系统字典"后,执行以下查询获取全部可用字典:** ```bash # 查询所有字典编码及其选项值 mysql -h127.0.0.1 -P3306 -uroot -proot jeecgboot3 -e " SELECT d.dict_code, d.dict_name, GROUP_CONCAT(i.item_text, '=', i.item_value ORDER BY i.sort_order SEPARATOR ', ') AS items FROM sys_dict d LEFT JOIN sys_dict_item i ON d.id = i.dict_id AND i.status = 1 WHERE d.del_flag = 0 GROUP BY d.dict_code, d.dict_name ORDER BY d.dict_code " ``` **匹配规则:** 拿到字典列表后,按以下优先级为字段匹配字典: 1. **用户明确指定** — 用户说"状态用字典 order_status",直接使用 2. **字段名精确匹配** — 字段名(如 `status`)与 dict_code 完全一致 3. **语义关键词匹配** — 字段注释含"状态/类型/级别/分类"等关键词,搜索 dict_name 包含相同关键词的字典 4. **不匹配** — 找不到合适字典时,不使用字典注解,按普通 Input 处理 **匹配成功后的效果:** - Entity: 自动添加 `@Dict(dicCode = "matched_dict_code")` - data.ts columns: `dataIndex` 使用 `fieldName_dictText` 后缀 - data.ts formSchema: `component` 使用 `JDictSelectTag`,`componentProps: { dictCode: 'matched_dict_code' }` - data.ts searchFormSchema: 同样使用 `JDictSelectTag` 组件 **展示格式:** 在 Step 3 表结构摘要中,匹配到字典的字段标注字典编码和选项值,如: ``` | 字段名 | 类型 | 控件 | 字典 | | status | varchar(10) | JDictSelectTag | order_status (待付款=0, 已付款=1, 已完成=2) | ``` ## 项目路径 | 类别 | 路径 | |------|------| | 后端根 | `{后端项目根目录}` | | 前端根 | `{前端项目根目录}` | | 后端代码 | `{module}/src/main/java/org/jeecg/modules/{entityPackage}/` | | 前端代码 | `src/views/{viewDir}/` | | Flyway SQL | `jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/` | ## 命名约定 - **表名**:snake_case(如 `biz_goods`) - **实体名**:表名转 PascalCase(如 `BizGoods`) - **entityPackage**:表名前缀或用户指定(如 `biz`) - **bussiPackage** 固定:`org.jeecg.modules` - **权限编码**:`{entityPackage}:{tableName}:add/edit/delete/deleteBatch/exportXls/importExcel` ## 智能字段推导 **用于新建表场景(从自然语言推导),或已有表但字段无注释时的补充推导:** | 语义关键词 | dbType | Java 类型 | vue3 组件 | vue3Native 组件 | |-----------|--------|----------|----------|----------------| | 名称/标题/编码 | varchar(100) | String | Input | a-input | | 金额/价格/费用 | decimal(10,2) | BigDecimal | InputNumber | a-input-number | | 数量/数目/个数 | int | Integer | InputNumber | a-input-number | | 状态/类型/级别 | varchar(10) | String | JDictSelectTag | JDictSelectTag | | 是否/开关 | varchar(2) | String | Switch | a-switch | | 日期/生日 | date | Date | DatePicker | a-date-picker | | 时间/日期时间 | datetime | Date | DatePicker(showTime) | a-date-picker(showTime) | | 备注/描述/说明 | text | String | InputTextArea | a-textarea | | 内容/富文本 | text | String | JEditor | JEditor | | 图片/头像/照片 | varchar(1000) | String | JImageUpload | JImageUpload | | 文件/附件 | varchar(1000) | String | JUpload | JUpload | | 用户/负责人 | varchar(32) | String | JSelectUserByDept | JSelectUserByDept | | 部门/组织 | varchar(32) | String | JSelectDept | JSelectDept | | 排序/序号 | int | Integer | InputNumber | a-input-number | **已有表场景的 DB类型→控件 映射(当字段无注释时使用):** | DB列类型 | Java类型 | 默认前端控件 | |---------|---------|-----------| | varchar(n) n<=200 | String | Input | | varchar(n) n>200 | String | InputTextArea | | text / longtext | String | InputTextArea | | int / tinyint | Integer | InputNumber | | bigint | Long | InputNumber | | decimal / double / float | BigDecimal | InputNumber | | date | Date | DatePicker | | datetime / timestamp | Date | DatePicker(showTime) | ## 主键策略(根据已有表结构自适应) | 表DDL中的主键定义 | Java类型 | @TableId | 说明 | |------------------|---------|----------|------| | `int AUTO_INCREMENT` | Integer | `@TableId(type = IdType.AUTO)` | int自增主键 | | `bigint AUTO_INCREMENT` | Long | `@TableId(type = IdType.AUTO)` | bigint自增主键 | | `varchar(36)` / `varchar(32)` 无AUTO_INCREMENT | String | `@TableId(type = IdType.ASSIGN_ID)` | JeecgBoot标准字符串主键 | | `bigint` 无AUTO_INCREMENT | Long | `@TableId(type = IdType.ASSIGN_ID)` | 雪花ID | **注意:** 当主键为 Integer/Long 类型时,Controller 中 `delete` 和 `queryById` 的参数类型也要对应调整。 ## 系统字段(按实际表结构判断) **不是所有表都有系统字段!** 生成前必须检查表是否实际包含这些字段,**只生成表中存在的字段**: | 字段 | 说明 | 不存在时的处理 | |------|------|--------------| | `create_by` | 创建人 | 不生成该属性 | | `create_time` | 创建时间 | 不生成该属性 | | `update_by` | 更新人 | 不生成该属性 | | `update_time` | 更新时间 | 不生成该属性 | | `sys_org_code` | 所属部门 | 不生成该属性 | 如果是**新建表**(用户自然语言描述需求),则默认添加全部系统字段。 如果是**已有表**(用户指定了表名且数据库中已存在),则必须根据实际 DDL 来决定。 树表额外字段:`pid`、`has_child`(同样需检查是否实际存在)。 ## 参考文件 生成代码前,**必须读取** 同目录下的 `codegen-reference.md` 获取完整代码模板骨架。