diff --git a/RuoYi-Vue/docs/superpowers/specs/2026-07-07-code-template-bundles-design.md b/RuoYi-Vue/docs/superpowers/specs/2026-07-07-code-template-bundles-design.md new file mode 100644 index 0000000..dbdd458 --- /dev/null +++ b/RuoYi-Vue/docs/superpowers/specs/2026-07-07-code-template-bundles-design.md @@ -0,0 +1,250 @@ +# 多代码模板包设计 + +## 目标 + +把当前固定使用 `qing` 的生成链路升级为可选择的代码模板包机制。`qing` 继续作为默认模板包,后续新增模板通过统一的模板包元数据、模板文件、结构树和生成选择策略接入,不再在生成服务里为每个模板反复增加硬编码分支。 + +第一期目标是支持多个技术栈或代码风格模板包,例如 `qing`、`qing-lite`、`vue3-plus`。行业业务提示词仍由现有 `industryTemplate` 表达,不和代码模板包混用。 + +## 当前上下文 + +现有 `qing` 生成能力由三部分组成: + +- 文件系统基线模板:`ruoyi-generator/src/main/resources/qing/*.vm`。 +- 数据库模板记录:`sys_template`、`sys_template_file`、`sys_project_structure`,种子主要在 `sql/qing_templates.sql` 和 `sql/db.sql`。 +- 生成服务选择逻辑:`GenProjectServiceImpl` 根据 `templateType` 解析模板,当前优先选择 9201、9202、9203 这三个可运行模板 ID。 + +这说明新增模板不能只复制一个目录。一个可用模板必须同时具备模板包标识、每类模板文件、结构树、输出路径约定、预览下载支持和运行预览兼容性。 + +## 用户体验 + +前台生成工作台在创建或编辑项目时增加“代码模板”选择。默认选中 `qing`。选择项来自后端接口,只展示启用状态的模板包。 + +预览页不再写死三类页签,而是读取当前项目模板包支持的目标类型: + +- `backend` +- `frontend` +- `admin_frontend` +- `sql` + +如果模板包不支持某一类,前端不展示对应页签,下载全部源码时也跳过该类。`frontendEnabled = 0` 时仍按现有逻辑隐藏用户前台。 + +## 数据模型 + +新增模板包表 `sys_template_bundle`: + +```sql +bundle_id bigint primary key, +bundle_code varchar(64) not null unique, +bundle_name varchar(100) not null, +description varchar(500), +status char(1) not null default '0', +is_default char(1) not null default '0', +support_backend char(1) not null default '1', +support_frontend char(1) not null default '1', +support_admin_frontend char(1) not null default '1', +support_sql char(1) not null default '1', +sort_order int default 0, +create_by varchar(64), +create_time datetime, +update_by varchar(64), +update_time datetime +``` + +扩展 `sys_template`: + +- 增加 `bundle_code varchar(64)`,用于把 `backend`、`frontend`、`admin_frontend` 等模板记录归属到同一个模板包。 +- 保留 `template_type` 表示目标类型,不改变现有模板文件和结构树关系。 +- `qing` 现有 9201、9202、9203 记录补充 `bundle_code = 'qing'`。 + +扩展前台项目表: + +- 增加 `code_template varchar(64)`,默认 `qing`。 +- `FrontProjectCreateRequest`、`FrontProjectUpdateRequest`、`AiGenerationTaskCreateRequest` 同步增加 `codeTemplate`。 +- `FrontProjectConverter.toGenProject` 把该字段传给 `GenProject`,供预览和下载使用。 + +## 后端架构 + +新增模板包服务: + +- `TemplateBundle` domain、mapper、service。 +- `listEnabledBundles()`:前端创建项目时使用。 +- `getBundle(code)`:生成服务解析模板时使用。 +- `getDefaultBundle()`:项目未指定时回退到默认模板包,默认应为 `qing`。 +- `getSupportedTemplateTypes(code, frontendEnabled)`:预览页和下载逻辑使用。 + +调整 `GenProjectServiceImpl`: + +- `resolveProjectTemplate(project, type)` 先读取 `project.codeTemplate`。 +- 未指定时回退默认模板包 `qing`。 +- 通过 `bundle_code + template_type + template_status = 0` 查询模板。 +- 移除 9201、9202、9203 作为固定优先模板的业务含义,只保留数据迁移兼容。 +- 如果项目后台手动绑定了 `sys_project_template`,仍优先使用绑定记录,以保持现有后台配置能力。 + +生成入口需要统一使用同一个模板包: + +- `getProjectStructure` +- `previewCode` +- `downloadStructure` +- `downloadAll` +- `run-preview` 源码准备 +- 一键生成中 `SOURCE_PREVIEW` 阶段的结构校验 + +## 模板资源组织 + +第一期可以继续以数据库模板为渲染来源,文件系统模板作为内置基线和测试对照。后续可逐步收敛到以下目录规范: + +```text +ruoyi-generator/src/main/resources/templates/ + qing/ + manifest.yml + backend/ + frontend/ + admin_frontend/ + vue3-plus/ + manifest.yml + backend/ + frontend/ + admin_frontend/ +``` + +`manifest.yml` 描述模板包基本信息、支持类型、推荐端口、模板文件清单和结构树种子来源。第一期不强制实现自动导入 manifest,但新增模板应按这个结构准备,避免继续把 `qing` 当作特殊目录。 + +## 数据流 + +1. 用户创建项目,选择 `codeTemplate`。 +2. 后端保存项目草稿,未传则写入默认模板包 `qing`。 +3. AI 生成蓝图、数据库、业务动作和页面设计时继续使用现有行业提示词,不受代码模板选择影响。 +4. 预览结构时,`GenProjectServiceImpl` 用 `project.codeTemplate + templateType` 找到模板记录。 +5. 根据模板记录读取 `sys_template_file`,根据模板 ID 读取 `sys_project_structure`。 +6. Velocity 渲染模板内容,结构树里的 `category` 对应模板文件名或路径。 +7. 下载全部源码时,后端遍历模板包支持的类型,合并 zip。 +8. 运行预览从下载出的结构中启动后端、用户前台和后台前端;不支持的类型跳过。 + +## 错误处理 + +模板包不存在或未启用: + +- 创建/更新项目时返回明确错误。 +- 老项目没有 `codeTemplate` 时回退默认模板包。 + +模板包缺少某个目标类型: + +- 前端不展示对应页签。 +- 后端收到不支持的 `templateType` 时返回“当前模板包不支持该生成类型”。 + +模板记录存在但文件缺失: + +- `getRequiredTemplateFiles` 继续抛出模板未配置文件错误。 +- 错误信息补充模板包 code、templateType 和 templateId,便于排查。 + +结构树 category 找不到模板文件: + +- 预览单文件时提示未找到模板文件。 +- 下载时记录失败模板路径,避免静默跳过。 + +运行预览不兼容: + +- 源码下载仍可用。 +- 运行预览返回失败状态和日志。 +- 模板包元数据可在后续增加 `run_preview_supported` 做显式控制。 + +## SQL 和迁移 + +第一期迁移脚本做这些事: + +- 创建 `sys_template_bundle`。 +- 给 `sys_template` 增加 `bundle_code`。 +- 给 `front_project` 增加 `code_template`。 +- 插入默认模板包 `qing`。 +- 将 9201、9202、9203 的 `bundle_code` 更新为 `qing`。 +- 更新历史前台项目 `code_template = 'qing'`。 +- 保证只有一个启用的默认模板包。 + +模板包种子建议独立文件: + +- `sql/code_template_bundles.sql`:模板包表结构和 qing 默认数据。 +- `sql/qing_templates.sql`:继续维护 qing 的模板文件和结构树。 +- `sql/db.sql`:整合完整初始化脚本。 + +## 前端改造 + +`easycode-web` 增加接口: + +- `listCodeTemplateBundles()` +- `getProjectSupportedTemplateTypes(projectId)` + +创建和编辑项目表单增加代码模板选择。展示文案建议: + +- `qing`:默认可运行 Spring Boot + Vue2 模板 +- 新模板:按模板包元数据展示名称和描述 + +`PreviewView` 改造: + +- `templateTypes` 来自后端,而不是固定数组。 +- 下载全部源码默认调用现有下载接口。 +- 单类下载时继续传 `templateType`。 +- 如果当前激活类型不在支持列表,自动切回第一个可用类型。 + +## 测试策略 + +后端单元测试: + +- 未指定 `codeTemplate` 时回退 `qing`。 +- 指定模板包时按 `bundle_code + template_type` 选择模板。 +- 后台项目模板绑定仍优先于模板包默认模板。 +- 禁用模板包不可用于新项目。 +- 不支持的 `templateType` 返回明确错误。 +- 老项目迁移后可以继续预览 backend、frontend、admin_frontend 和 sql。 + +模板一致性测试: + +- `qing` 模板包的 9201、9202、9203 都能找到文件和结构树。 +- 结构树 `category` 都能匹配模板文件名或路径。 +- 复制出的测试模板包不会被 9201、9202、9203 固定优先逻辑覆盖。 + +前端测试: + +- 创建项目表单展示代码模板选择。 +- 未选择时提交默认 `qing`。 +- 预览页按后端返回的支持类型渲染页签。 +- `frontendEnabled = 0` 时隐藏用户前台。 + +人工验收: + +1. 导入迁移脚本。 +2. 创建项目,不手动选择模板,确认使用 `qing`。 +3. 创建项目,选择测试模板包,确认预览结构来自新模板包。 +4. 下载全部源码,确认只包含模板包支持的目标类型。 +5. 启动运行预览,确认 qing 模板仍可运行。 + +## 分期 + +第一期: + +- 数据库增加模板包和项目模板选择字段。 +- 后端模板包服务和选择策略。 +- 前台创建/编辑项目支持代码模板选择。 +- 预览页动态读取支持类型。 +- qing 作为默认模板包完成迁移。 + +第二期: + +- 引入 `manifest.yml` 导入工具。 +- 增加模板包复制、启停、导入导出。 +- 模板包运行预览能力声明。 +- 模板包版本管理。 + +第三期: + +- 模板市场化管理。 +- 模板包依赖能力声明,例如业务块、图表、文件上传、认证方式。 +- 模板包质量检查和在线试生成。 + +## 自检 + +- 范围聚焦在代码模板包,不混入行业业务模板。 +- `qing` 作为默认行为保留,老项目有回退路径。 +- 模板选择逻辑从固定 ID 改为模板包 code,不再扩大硬编码。 +- 数据库模板文件和结构树仍沿用现有模型,避免一次性重写生成器。 +- 前端页签和下载逻辑从模板包能力派生,避免新增模板后继续改页面常量。