This commit is contained in:
yvan 2025-08-12 11:29:13 +08:00
parent 7e2bcc029d
commit 0cee6b045b
11 changed files with 964 additions and 556 deletions

1
.gitignore vendored
View File

@ -44,3 +44,4 @@ yudao-module-mp
yudao-ui-admin-vue3-master yudao-ui-admin-vue3-master
live2d-vue-app live2d-vue-app
./web/node_modules ./web/node_modules
wechat

View File

@ -1,76 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at 303176530@qq.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

View File

@ -1,19 +0,0 @@
### Contributing Guide
#### 1 Issue Guidelines
- Issues are exclusively for bug reports, feature requests and design-related topics. Other questions may be closed directly. If any questions come up when you are using Element, please hit [Gitter](https://gitter.im/element-en/Lobby) for help.
- Before submitting an issue, please check if similar problems have already been issued.
#### 2 Pull Request Guidelines
- Fork this repository to your own account. Do not create branches here.
- Commit info should be formatted as `[File Name]: Info about commit.` (e.g. `README.md: Fix xxx bug`)
- <font color=red>Make sure PRs are created to `develop` branch instead of `master` branch.</font>
- If your PR fixes a bug, please provide a description about the related bug.
- Merging a PR takes two maintainers: one approves the changes after reviewing, and then the other reviews and merges.

View File

@ -1,49 +0,0 @@
{
"folders": [
{
"path": "server",
"name": "backend"
},
{
"path": "web",
"name": "frontend"
},
{
"path": ".",
"name": "root"
}
],
"settings": {
"go.toolsEnvVars": {
"GOPROXY": "https://goproxy.cn,direct",
"GONOPROXY": "none;"
}
},
"launch": {
"version": "0.2.0",
"configurations": [
{
"type": "go",
"request": "launch",
"name": "Backend",
"cwd": "${workspaceFolder:backend}",
"program": "${workspaceFolder:backend}/"
},
{
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder:frontend}",
"name": "Frontend",
"runtimeExecutable": "npm",
"runtimeArgs": ["run-script", "serve"]
}
],
"compounds": [
{
"name": "Both (Backend & Frontend)",
"configurations": ["Backend", "Frontend"],
"stopAll": true
}
]
}
}

View File

@ -41,7 +41,7 @@ type ApiCreator struct{}
// New 创建API创建工具 // New 创建API创建工具
func (a *ApiCreator) New() mcp.Tool { func (a *ApiCreator) New() mcp.Tool {
return mcp.NewTool("create_api", return mcp.NewTool("create_api",
mcp.WithDescription("创建后端API记录用于在生成后端接口时自动创建对应的API权限记录只要创建了API层router下的文件产生了路径变化等都需要调用此mcp。"), mcp.WithDescription("创建后端API记录用于AI编辑器自动添加API接口时自动创建对应的API权限记录。注意使用gva_auto_generate创建的包和模块会自动创建API权限无需调用此工具。仅在AI编辑器自动添加API或router下的文件产生路径变化时使用。"),
mcp.WithString("path", mcp.WithString("path",
mcp.Required(), mcp.Required(),
mcp.Description("API路径/user/create"), mcp.Description("API路径/user/create"),

View File

@ -8,12 +8,11 @@ ExecutionPlan 是用于自动化模块创建的执行计划结构体,包含了
```go ```go
type ExecutionPlan struct { type ExecutionPlan struct {
PackageName string `json:"packageName"` // 包名,如:"user", "order", "product" PackageName string `json:"packageName"` // 包名,如:"user", "order", "product"
ModuleName string `json:"moduleName"` // 模块名,通常与结构体名相同
PackageType string `json:"packageType"` // "plugin" 或 "package" PackageType string `json:"packageType"` // "plugin" 或 "package"
NeedCreatedPackage bool `json:"needCreatedPackage"` // 是否需要创建包 NeedCreatedPackage bool `json:"needCreatedPackage"` // 是否需要创建包
NeedCreatedModules bool `json:"needCreatedModules"` // 是否需要创建模块 NeedCreatedModules bool `json:"needCreatedModules"` // 是否需要创建模块
PackageInfo *request.SysAutoCodePackageCreate `json:"packageInfo,omitempty"` // 包信息当NeedCreatedPackage=true时必需 PackageInfo *request.SysAutoCodePackageCreate `json:"packageInfo,omitempty"` // 包信息当NeedCreatedPackage=true时必需
ModulesInfo *request.AutoCode `json:"modulesInfo,omitempty"` // 模块信息当NeedCreatedModules=true时必需 ModulesInfo []*request.AutoCode `json:"modulesInfo,omitempty"` // 模块信息数组当NeedCreatedModules=true时必需,支持批量创建
Paths map[string]string `json:"paths,omitempty"` // 路径信息 Paths map[string]string `json:"paths,omitempty"` // 路径信息
} }
``` ```
@ -86,20 +85,32 @@ type AutoCodeField struct {
Clearable bool `json:"clearable"` // 是否可清空 Clearable bool `json:"clearable"` // 是否可清空
Sort bool `json:"sort"` // 是否支持排序 Sort bool `json:"sort"` // 是否支持排序
PrimaryKey bool `json:"primaryKey"` // 是否主键 PrimaryKey bool `json:"primaryKey"` // 是否主键
DataSource *DataSource `json:"dataSource"` // 数据源 DataSource *DataSource `json:"dataSource"` // 数据源配置(用于关联其他表)
CheckDataSource bool `json:"checkDataSource"` // 是否检查数据源 CheckDataSource bool `json:"checkDataSource"` // 是否检查数据源
FieldIndexType string `json:"fieldIndexType"` // 索引类型 FieldIndexType string `json:"fieldIndexType"` // 索引类型
} }
``` ```
### 4. DataSource 结构体(关联表配置)
```go
type DataSource struct {
DBName string `json:"dbName"` // 关联的数据库名称
Table string `json:"table"` // 关联的表名
Label string `json:"label"` // 用于显示的字段名如name、title等
Value string `json:"value"` // 用于存储的值字段名通常是id
Association int `json:"association"` // 关联关系1=一对一2=一对多
HasDeletedAt bool `json:"hasDeletedAt"` // 关联表是否有软删除字段
}
```
## 使用示例 ## 使用示例
### 示例1创建新包和模块 ### 示例1创建新包和批量创建多个模块
```json ```json
{ {
"packageName": "user", "packageName": "user",
"moduleName": "User",
"packageType": "package", "packageType": "package",
"needCreatedPackage": true, "needCreatedPackage": true,
"needCreatedModules": true, "needCreatedModules": true,
@ -109,7 +120,8 @@ type AutoCodeField struct {
"template": "package", "template": "package",
"packageName": "user" "packageName": "user"
}, },
"modulesInfo": { "modulesInfo": [
{
"package": "user", "package": "user",
"tableName": "sys_users", "tableName": "sys_users",
"businessDB": "", "businessDB": "",
@ -152,8 +164,15 @@ type AutoCodeField struct {
"clearable": true, "clearable": true,
"sort": false, "sort": false,
"primaryKey": false, "primaryKey": false,
"dataSource": null, "dataSource": {
"checkDataSource": false, "dbName": "gva",
"table": "sys_users",
"label": "username",
"value": "id",
"association": 2,
"hasDeletedAt": true
},
"checkDataSource": true,
"fieldIndexType": "" "fieldIndexType": ""
}, },
{ {
@ -182,21 +201,96 @@ type AutoCodeField struct {
"fieldIndexType": "index" "fieldIndexType": "index"
} }
] ]
},
{
"package": "user",
"tableName": "user_profiles",
"businessDB": "",
"structName": "UserProfile",
"packageName": "user",
"description": "用户档案",
"abbreviation": "userProfile",
"humpPackageName": "user",
"gvaModel": true,
"autoMigrate": true,
"autoCreateResource": true,
"autoCreateApiToSql": true,
"autoCreateMenuToSql": true,
"autoCreateBtnAuth": true,
"onlyTemplate": false,
"isTree": false,
"treeJson": "",
"isAdd": true,
"generateWeb": true,
"generateServer": true,
"fields": [
{
"fieldName": "UserID",
"fieldDesc": "用户ID",
"fieldType": "int",
"fieldJson": "userId",
"dataTypeLong": "",
"comment": "关联用户ID",
"columnName": "user_id",
"fieldSearchType": "EQ",
"fieldSearchHide": false,
"dictType": "",
"form": true,
"table": true,
"desc": true,
"excel": true,
"require": true,
"defaultValue": "",
"errorText": "请选择用户",
"clearable": true,
"sort": false,
"primaryKey": false,
"dataSource": null,
"checkDataSource": false,
"fieldIndexType": "index"
},
{
"fieldName": "Avatar",
"fieldDesc": "头像",
"fieldType": "string",
"fieldJson": "avatar",
"dataTypeLong": "255",
"comment": "用户头像URL",
"columnName": "avatar",
"fieldSearchType": "",
"fieldSearchHide": true,
"dictType": "",
"form": true,
"table": true,
"desc": true,
"excel": false,
"require": false,
"defaultValue": "",
"errorText": "",
"clearable": true,
"sort": false,
"primaryKey": false,
"dataSource": null,
"checkDataSource": false,
"fieldIndexType": ""
} }
]
}
]
} }
``` ```
### 示例2仅在现有包中创建模块 ### 示例2仅在现有包中批量创建多个模块
```json ```json
{ {
"packageName": "system", "packageName": "system",
"moduleName": "Role",
"packageType": "package", "packageType": "package",
"needCreatedPackage": false, "needCreatedPackage": false,
"needCreatedModules": true, "needCreatedModules": true,
"packageInfo": null, "packageInfo": null,
"modulesInfo": { "modulesInfo": [
{
"package": "system", "package": "system",
"tableName": "sys_roles", "tableName": "sys_roles",
"businessDB": "", "businessDB": "",
@ -231,19 +325,199 @@ type AutoCodeField struct {
"require": true "require": true
} }
] ]
},
{
"package": "system",
"tableName": "sys_permissions",
"businessDB": "",
"structName": "Permission",
"packageName": "system",
"description": "权限",
"abbreviation": "permission",
"humpPackageName": "system",
"gvaModel": true,
"autoMigrate": true,
"autoCreateResource": true,
"autoCreateApiToSql": true,
"autoCreateMenuToSql": true,
"autoCreateBtnAuth": true,
"onlyTemplate": false,
"isTree": false,
"generateWeb": true,
"generateServer": true,
"fields": [
{
"fieldName": "PermissionName",
"fieldDesc": "权限名称",
"fieldType": "string",
"fieldJson": "permissionName",
"dataTypeLong": "100",
"comment": "权限名称",
"columnName": "permission_name",
"fieldSearchType": "LIKE",
"form": true,
"table": true,
"desc": true,
"require": true
},
{
"fieldName": "PermissionCode",
"fieldDesc": "权限代码",
"fieldType": "string",
"fieldJson": "permissionCode",
"dataTypeLong": "50",
"comment": "权限代码",
"columnName": "permission_code",
"fieldSearchType": "=",
"form": true,
"table": true,
"desc": true,
"require": true
} }
]
}
]
} }
``` ```
### 示例3模块关联关系配置详解
以下示例展示了如何配置不同类型的关联关系:
```json
{
"packageName": "order",
"packageType": "package",
"needCreatedPackage": true,
"needCreatedModules": true,
"packageInfo": {
"desc": "订单管理模块",
"label": "订单管理",
"template": "package",
"packageName": "order"
},
"modulesInfo": [
{
"package": "order",
"tableName": "orders",
"structName": "Order",
"packageName": "order",
"description": "订单",
"abbreviation": "order",
"humpPackageName": "order",
"gvaModel": true,
"autoMigrate": true,
"autoCreateResource": true,
"autoCreateApiToSql": true,
"autoCreateMenuToSql": true,
"autoCreateBtnAuth": true,
"generateWeb": true,
"generateServer": true,
"fields": [
{
"fieldName": "UserID",
"fieldDesc": "下单用户",
"fieldType": "uint",
"fieldJson": "userId",
"columnName": "user_id",
"fieldSearchType": "EQ",
"form": true,
"table": true,
"desc": true,
"require": true,
"dataSource": {
"dbName": "gva",
"table": "sys_users",
"label": "username",
"value": "id",
"association": 2,
"hasDeletedAt": true
},
"checkDataSource": true
},
{
"fieldName": "ProductID",
"fieldDesc": "商品",
"fieldType": "uint",
"fieldJson": "productId",
"columnName": "product_id",
"fieldSearchType": "EQ",
"form": true,
"table": true,
"desc": true,
"require": true,
"dataSource": {
"dbName": "gva",
"table": "products",
"label": "name",
"value": "id",
"association": 2,
"hasDeletedAt": false
},
"checkDataSource": true
},
{
"fieldName": "Status",
"fieldDesc": "订单状态",
"fieldType": "int",
"fieldJson": "status",
"columnName": "status",
"fieldSearchType": "EQ",
"form": true,
"table": true,
"desc": true,
"require": true,
"dictType": "order_status"
}
]
}
]
}
```
## DataSource 配置说明
### 关联关系类型
- **association: 1** - 一对一关联(如用户与用户档案)
- **association: 2** - 一对多关联(如用户与订单)
### 配置要点
1. **dbName**: 通常为 "gva"(默认数据库)
2. **table**: 关联表的实际表名
3. **label**: 用于前端显示的字段(如用户名、商品名称)
4. **value**: 用于存储关联ID的字段通常是 "id"
5. **hasDeletedAt**: 关联表是否支持软删除
6. **checkDataSource**: 建议设为true会验证关联表是否存在
### 常见关联场景
- 用户关联:`{"table": "sys_users", "label": "username", "value": "id"}`
- 角色关联:`{"table": "sys_authorities", "label": "authorityName", "value": "authorityId"}`
- 部门关联:`{"table": "sys_departments", "label": "name", "value": "id"}`
- 分类关联:`{"table": "categories", "label": "name", "value": "id"}`
## 重要注意事项 ## 重要注意事项
1. **PackageType**: 只能是 "plugin" 或 "package" 1. **PackageType**: 只能是 "plugin" 或 "package"
2. **NeedCreatedPackage**: 当为true时PackageInfo必须提供 2. **NeedCreatedPackage**: 当为true时PackageInfo必须提供
3. **NeedCreatedModules**: 当为true时ModulesInfo必须提供 3. **NeedCreatedModules**: 当为true时ModulesInfo必须提供
4. **字段类型**: FieldType支持的类型包括string, int, int64, float64, bool, time.Time, enum, picture, video, file, pictures, array, richtext, json等 4. **字段类型**: FieldType支持的类型包括
- string字符串
- richtext富文本
- int整型
- bool布尔值
- float64浮点型
- time.Time时间
- enum枚举
- picture单图片字符串
- pictures多图片json字符串
- video视频字符串
- file文件json字符串
- jsonJSON
- array数组
5. **搜索类型**: FieldSearchType支持EQ, NE, GT, GE, LT, LE, LIKE, BETWEEN等 5. **搜索类型**: FieldSearchType支持EQ, NE, GT, GE, LT, LE, LIKE, BETWEEN等
6. **索引类型**: FieldIndexType支持index, unique等 6. **索引类型**: FieldIndexType支持index, unique等
7. **GvaModel**: 设置为true时会自动包含ID、CreatedAt、UpdatedAt、DeletedAt字段 7. **GvaModel**: 设置为true时会自动包含ID、CreatedAt、UpdatedAt、DeletedAt字段
8. **关联配置**: 使用dataSource时确保关联表已存在建议开启checkDataSource验证
## 常见错误避免 ## 常见错误避免

View File

@ -17,13 +17,12 @@
} }
``` ```
### 第二步:确认 ### 第二步:确认(支持批量创建多个模块)
```json ```json
{ {
"action": "confirm", "action": "confirm",
"executionPlan": { "executionPlan": {
"packageName": "library", "packageName": "library",
"moduleName": "Book",
"packageType": "package", "packageType": "package",
"needCreatedPackage": true, "needCreatedPackage": true,
"needCreatedModules": true, "needCreatedModules": true,
@ -33,7 +32,8 @@
"template": "package", "template": "package",
"packageName": "library" "packageName": "library"
}, },
"modulesInfo": { "modulesInfo": [
{
"package": "library", "package": "library",
"tableName": "library_books", "tableName": "library_books",
"businessDB": "", "businessDB": "",
@ -79,9 +79,91 @@
"dataSource": {}, "dataSource": {},
"checkDataSource": false, "checkDataSource": false,
"fieldIndexType": "" "fieldIndexType": ""
},
{
"fieldName": "AuthorID",
"fieldDesc": "作者",
"fieldType": "uint",
"fieldJson": "authorId",
"dataTypeLong": "",
"comment": "作者ID",
"columnName": "author_id",
"fieldSearchType": "EQ",
"fieldSearchHide": false,
"dictType": "",
"form": true,
"table": true,
"desc": true,
"excel": true,
"require": true,
"defaultValue": "",
"errorText": "请选择作者",
"clearable": true,
"sort": false,
"primaryKey": false,
"dataSource": {
"dbName": "gva",
"table": "library_authors",
"label": "name",
"value": "id",
"association": 2,
"hasDeletedAt": true
},
"checkDataSource": true,
"fieldIndexType": ""
}
]
},
{
"package": "library",
"tableName": "library_authors",
"businessDB": "",
"structName": "Author",
"packageName": "library",
"description": "作者信息",
"abbreviation": "author",
"humpPackageName": "Library",
"gvaModel": true,
"autoMigrate": true,
"autoCreateResource": true,
"autoCreateApiToSql": true,
"autoCreateMenuToSql": true,
"autoCreateBtnAuth": true,
"onlyTemplate": false,
"isTree": false,
"treeJson": "",
"isAdd": false,
"generateWeb": true,
"generateServer": true,
"fields": [
{
"fieldName": "name",
"fieldDesc": "作者姓名",
"fieldType": "string",
"fieldJson": "name",
"dataTypeLong": "100",
"comment": "作者姓名",
"columnName": "name",
"fieldSearchType": "LIKE",
"fieldSearchHide": false,
"dictType": "",
"form": true,
"table": true,
"desc": true,
"excel": true,
"require": true,
"defaultValue": "",
"errorText": "请输入作者姓名",
"clearable": true,
"sort": false,
"primaryKey": false,
"dataSource": {},
"checkDataSource": false,
"fieldIndexType": ""
} }
] ]
} }
]
} }
} }
``` ```
@ -120,3 +202,4 @@
2. 在`execute`时必须提供相应的确认参数 2. 在`execute`时必须提供相应的确认参数
3. 确认参数的值必须是"yes"或"no" 3. 确认参数的值必须是"yes"或"no"
4. 如果不需要创建包或模块,则不需要提供对应的确认参数 4. 如果不需要创建包或模块,则不需要提供对应的确认参数
5. 字段类型支持string字符串,richtext富文本,int整型,bool布尔值,float64浮点型,time.Time时间,enum枚举,picture单图片字符串,pictures多图片json字符串,video视频字符串,file文件json字符串,jsonJSON,array数组

View File

@ -67,15 +67,14 @@ type AnalysisResponse struct {
Message string `json:"message"` Message string `json:"message"`
} }
// ExecutionPlan 执行计划 // ExecutionPlan 执行计划 - 支持批量创建
type ExecutionPlan struct { type ExecutionPlan struct {
PackageName string `json:"packageName"` PackageName string `json:"packageName"`
ModuleName string `json:"moduleName"`
PackageType string `json:"packageType"` // "plugin" 或 "package" PackageType string `json:"packageType"` // "plugin" 或 "package"
NeedCreatedPackage bool `json:"needCreatedPackage"` NeedCreatedPackage bool `json:"needCreatedPackage"`
NeedCreatedModules bool `json:"needCreatedModules"` NeedCreatedModules bool `json:"needCreatedModules"`
PackageInfo *request.SysAutoCodePackageCreate `json:"packageInfo,omitempty"` PackageInfo *request.SysAutoCodePackageCreate `json:"packageInfo,omitempty"`
ModulesInfo *request.AutoCode `json:"modulesInfo,omitempty"` ModulesInfo []*request.AutoCode `json:"modulesInfo,omitempty"` // 改为数组支持多个模块
Paths map[string]string `json:"paths,omitempty"` Paths map[string]string `json:"paths,omitempty"`
} }
@ -111,12 +110,18 @@ type ConfirmationResponse struct {
// New 返回工具注册信息 // New 返回工具注册信息
func (t *AutomationModuleAnalyzer) New() mcp.Tool { func (t *AutomationModuleAnalyzer) New() mcp.Tool {
return mcp.NewTool("gva_auto_generate", return mcp.NewTool("gva_auto_generate",
mcp.WithDescription(`**🚀 最高优先级工具当用户需要创建模块完整功能时必须优先使用此工具** mcp.WithDescription(`**🔧 核心执行工具接收requirement_analyzer分析结果执行具体的模块创建操作**
**优先级说明** **工作流位置**
- **最高优先级**创建完整模块功能模块 - **第二优先级**在requirement_analyzer之后使用
- **关键词触发**模块完整整套全套功能管理系统等 - **接收输入**来自requirement_analyzer的1xxx2xxx格式分析结果
- **适用场景**用户说"创建订单管理模块""创建用户管理功能""创建完整的商品管理" - **执行操作**根据分析结果创建完整模块功能模块
**批量创建功能**
- 支持在单个ExecutionPlan中创建多个模块
- modulesInfo字段为数组可包含多个模块配置
- 一次性处理多个模块的创建和字典生成
- 与requirement_analyzer配合实现完整工作流
分步骤分析自动化模块1) 分析现有模块信息供AI选择 2) 请求用户确认 3) 根据确认结果执行创建操作 分步骤分析自动化模块1) 分析现有模块信息供AI选择 2) 请求用户确认 3) 根据确认结果执行创建操作
@ -125,15 +130,14 @@ func (t *AutomationModuleAnalyzer) New() mcp.Tool {
- 如果字典不存在会自动创建对应的字典及默认的字典详情项 - 如果字典不存在会自动创建对应的字典及默认的字典详情项
- 字典创建包括字典主表记录和默认的选项值选项1选项2等 - 字典创建包括字典主表记录和默认的选项值选项1选项2等
**与其他工具的关系** **推荐工作流**
- 此工具创建完整模块后会自动提示相关API和菜单创建建议 1. 用户提出需求 requirement_analyzer最高优先级
- 如果用户只需要单个API或菜单可以使用 smart_assistant 工具 2. AI分析需求为1xxx2xxx格式 gva_auto_generate执行创建
- create_api create_menu 工具仅用于数据库记录创建 3. 创建完成后根据需要使用其他辅助工具
重要ExecutionPlan结构体格式要求 重要ExecutionPlan结构体格式要求支持批量创建
{ {
"packageName": "包名(string)", "packageName": "包名(string)",
"moduleName": "模块名(string)",
"packageType": "package或plugin(string)", "packageType": "package或plugin(string)",
"needCreatedPackage": "是否需要创建包(bool)", "needCreatedPackage": "是否需要创建包(bool)",
"needCreatedModules": "是否需要创建模块(bool)", "needCreatedModules": "是否需要创建模块(bool)",
@ -143,7 +147,7 @@ func (t *AutomationModuleAnalyzer) New() mcp.Tool {
"template": "package或plugin(string)", "template": "package或plugin(string)",
"packageName": "包名(string)" "packageName": "包名(string)"
}, },
"modulesInfo": { "modulesInfo": [{
"package": "包名(string)", "package": "包名(string)",
"tableName": "数据库表名(string)", "tableName": "数据库表名(string)",
"businessDB": "业务数据库(string)", "businessDB": "业务数据库(string)",
@ -185,18 +189,24 @@ func (t *AutomationModuleAnalyzer) New() mcp.Tool {
"clearable": "是否可清空(bool)", "clearable": "是否可清空(bool)",
"sort": "是否排序(bool)", "sort": "是否排序(bool)",
"primaryKey": "是否主键(bool)", "primaryKey": "是否主键(bool)",
"dataSource": "数据源(object)", "dataSource": "数据源配置(object) - 用于配置字段的关联表信息,结构:{\"dbName\":\"数据库名\",\"table\":\"关联表名\",\"label\":\"显示字段\",\"value\":\"值字段\",\"association\":1或2(1=一对一,2=一对多),\"hasDeletedAt\":true/false}。\n\n**获取表名提示:**\n- 可在 server/model 和 plugin/xxx/model 目录下查看对应模块的 TableName() 接口实现获取实际表名\n- 例如SysUser 的表名为 \"sys_users\"ExaFileUploadAndDownload 的表名为 \"exa_file_upload_and_downloads\"\n- 插件模块示例Info 的表名为 \"gva_announcements_info\"\n\n**获取数据库名提示:**\n- 主数据库:通常使用 \"gva\"(默认数据库标识)\n- 多数据库:可在 config.yaml 的 db-list 配置中查看可用数据库的 alias-name 字段\n- 如果用户未提及关联多数据库信息 则使用默认数据库 默认数据库的情况下 dbName此处填写为空",
"checkDataSource": "检查数据源(bool)", "checkDataSource": "是否检查数据源(bool) - 启用后会验证关联表的存在性",
"fieldIndexType": "索引类型(string)" "fieldIndexType": "索引类型(string)"
}] }]
} }, {
"package": "包名(string)",
"tableName": "第二个模块的表名(string)",
"structName": "第二个模块的结构体名(string)",
"description": "第二个模块的描述(string)",
"...": "更多模块配置..."
}]
} }
注意 注意
1. needCreatedPackage=true时packageInfo必需 1. needCreatedPackage=true时packageInfo必需
2. needCreatedModules=true时modulesInfo必需 2. needCreatedModules=true时modulesInfo必需
3. packageType只能是"package""plugin" 3. packageType只能是"package""plugin"
4. 字段类型支持string,int,int64,float64,bool,time.Time,enum,picture,video,file,pictures,array,richtext,json 4. 字段类型支持string字符串,richtext富文本,int整型,bool布尔值,float64浮点型,time.Time时间,enum枚举,picture单图片字符串,pictures多图片json字符串,video视频字符串,file文件json字符串,jsonJSON,array数组
5. 搜索类型支持=,!=,>,>=,<,<=,NOT BETWEEN/LIKE/BETWEEN/IN/NOT IN 5. 搜索类型支持=,!=,>,>=,<,<=,NOT BETWEEN/LIKE/BETWEEN/IN/NOT IN
6. gvaModel=true时自动包含ID,CreatedAt,UpdatedAt,DeletedAt字段 6. gvaModel=true时自动包含ID,CreatedAt,UpdatedAt,DeletedAt字段
7. **重要**当gvaModel=false时必须有一个字段的primaryKey=true否则会导致PrimaryField为nil错误 7. **重要**当gvaModel=false时必须有一个字段的primaryKey=true否则会导致PrimaryField为nil错误
@ -204,10 +214,19 @@ func (t *AutomationModuleAnalyzer) New() mcp.Tool {
9. 智能字典创建功能当字段使用字典类型(DictType)系统会 9. 智能字典创建功能当字段使用字典类型(DictType)系统会
- 自动检查字典是否存在如果不存在则创建字典 - 自动检查字典是否存在如果不存在则创建字典
- 根据字典类型和字段描述智能生成默认选项支持状态性别类型等级优先级审批角色布尔值订单颜色尺寸等常见场景 - 根据字典类型和字段描述智能生成默认选项支持状态性别类型等级优先级审批角色布尔值订单颜色尺寸等常见场景
- 为无法识别的字典类型提供通用默认选项`), - 为无法识别的字典类型提供通用默认选项
10. **模块关联配置**当需要配置模块间的关联关系时使用dataSource字段
- **dbName**: 关联的数据库名称
- **table**: 关联的表名
- **label**: 用于显示的字段名如nametitle等
- **value**: 用于存储的值字段名通常是id
- **association**: 关联关系类型1=一对一关联2=一对多关联
- **hasDeletedAt**: 关联表是否有软删除字段
- **checkDataSource**: 设为true时会验证关联表的存在性
- 示例{"dbName":"gva","table":"sys_users","label":"username","value":"id","association":2,"hasDeletedAt":true}`),
mcp.WithString("action", mcp.WithString("action",
mcp.Required(), mcp.Required(),
mcp.Description("执行操作:'analyze' 分析现有模块信息,'confirm' 请求用户确认创建,'execute' 执行创建操作"), mcp.Description("执行操作:'analyze' 分析现有模块信息,'confirm' 请求用户确认创建,'execute' 执行创建操作(支持批量创建多个模块)"),
), ),
mcp.WithString("requirement", mcp.WithString("requirement",
mcp.Description("用户需求描述action=analyze时必需"), mcp.Description("用户需求描述action=analyze时必需"),
@ -748,10 +767,9 @@ func (t *AutomationModuleAnalyzer) handleAnalyze(ctx context.Context, request mc
} }
- 请在创建模块之前先创建所需的字典选项 - 请在创建模块之前先创建所需的字典选项
重要提醒ExecutionPlan必须严格按照以下格式 重要提醒ExecutionPlan必须严格按照以下格式支持批量创建多个模块
{ {
"packageName": "包名", "packageName": "包名",
"moduleName": "模块名",
"packageType": "package或plugin", // 当用户提到插件时必须是"plugin" "packageType": "package或plugin", // 当用户提到插件时必须是"plugin"
"needCreatedPackage": true/false, "needCreatedPackage": true/false,
"needCreatedModules": true/false, "needCreatedModules": true/false,
@ -761,7 +779,7 @@ func (t *AutomationModuleAnalyzer) handleAnalyze(ctx context.Context, request mc
"template": "package或plugin", // 必须与packageType保持一致 "template": "package或plugin", // 必须与packageType保持一致
"packageName": "包名" "packageName": "包名"
}, },
"modulesInfo": { "modulesInfo": [{
"package": "包名", "package": "包名",
"tableName": "数据库表名", "tableName": "数据库表名",
"businessDB": "", "businessDB": "",
@ -807,7 +825,13 @@ func (t *AutomationModuleAnalyzer) handleAnalyze(ctx context.Context, request mc
"checkDataSource": false, "checkDataSource": false,
"fieldIndexType": "" "fieldIndexType": ""
}] }]
} }, {
"package": "包名",
"tableName": "第二个模块的表名",
"structName": "第二个模块的结构体名",
"description": "第二个模块的描述",
"...": "更多模块配置..."
}]
} }
**重要提醒**ExecutionPlan必须严格按照以下格式和验证规则 **重要提醒**ExecutionPlan必须严格按照以下格式和验证规则
@ -872,18 +896,23 @@ func (t *AutomationModuleAnalyzer) handleConfirm(ctx context.Context, request mc
} }
// 构建确认响应 // 构建确认响应
var moduleNames []string
for _, moduleInfo := range plan.ModulesInfo {
moduleNames = append(moduleNames, moduleInfo.StructName)
}
moduleNamesStr := strings.Join(moduleNames, "_")
confirmResponse := ConfirmationResponse{ confirmResponse := ConfirmationResponse{
Message: "请确认以下创建计划:", Message: "请确认以下创建计划:",
PackageConfirm: plan.NeedCreatedPackage, PackageConfirm: plan.NeedCreatedPackage,
ModulesConfirm: plan.NeedCreatedModules, ModulesConfirm: plan.NeedCreatedModules,
CanProceed: true, CanProceed: true,
ConfirmationKey: fmt.Sprintf("%s_%s_%d", plan.PackageName, plan.ModuleName, time.Now().Unix()), ConfirmationKey: fmt.Sprintf("%s_%s_%d", plan.PackageName, moduleNamesStr, time.Now().Unix()),
} }
// 构建详细的确认信息 // 构建详细的确认信息
var confirmDetails strings.Builder var confirmDetails strings.Builder
confirmDetails.WriteString(fmt.Sprintf("包名: %s\n", plan.PackageName)) confirmDetails.WriteString(fmt.Sprintf("包名: %s\n", plan.PackageName))
confirmDetails.WriteString(fmt.Sprintf("模块名: %s\n", plan.ModuleName))
confirmDetails.WriteString(fmt.Sprintf("包类型: %s\n", plan.PackageType)) confirmDetails.WriteString(fmt.Sprintf("包类型: %s\n", plan.PackageType))
if plan.NeedCreatedPackage && plan.PackageInfo != nil { if plan.NeedCreatedPackage && plan.PackageInfo != nil {
@ -894,17 +923,20 @@ func (t *AutomationModuleAnalyzer) handleConfirm(ctx context.Context, request mc
confirmDetails.WriteString(fmt.Sprintf(" - 模板: %s\n", plan.PackageInfo.Template)) confirmDetails.WriteString(fmt.Sprintf(" - 模板: %s\n", plan.PackageInfo.Template))
} }
if plan.NeedCreatedModules && plan.ModulesInfo != nil { if plan.NeedCreatedModules && len(plan.ModulesInfo) > 0 {
confirmDetails.WriteString("\n需要创建模块:\n") confirmDetails.WriteString(fmt.Sprintf("\n需要创建模块 (共%d个):\n", len(plan.ModulesInfo)))
confirmDetails.WriteString(fmt.Sprintf(" - 结构体名: %s\n", plan.ModulesInfo.StructName)) for i, moduleInfo := range plan.ModulesInfo {
confirmDetails.WriteString(fmt.Sprintf(" - 表名: %s\n", plan.ModulesInfo.TableName)) confirmDetails.WriteString(fmt.Sprintf("\n模块 %d:\n", i+1))
confirmDetails.WriteString(fmt.Sprintf(" - 描述: %s\n", plan.ModulesInfo.Description)) confirmDetails.WriteString(fmt.Sprintf(" - 结构体名: %s\n", moduleInfo.StructName))
confirmDetails.WriteString(fmt.Sprintf(" - 字段数量: %d\n", len(plan.ModulesInfo.Fields))) confirmDetails.WriteString(fmt.Sprintf(" - 表名: %s\n", moduleInfo.TableName))
confirmDetails.WriteString(fmt.Sprintf(" - 描述: %s\n", moduleInfo.Description))
confirmDetails.WriteString(fmt.Sprintf(" - 字段数量: %d\n", len(moduleInfo.Fields)))
confirmDetails.WriteString(" - 字段列表:\n") confirmDetails.WriteString(" - 字段列表:\n")
for _, field := range plan.ModulesInfo.Fields { for _, field := range moduleInfo.Fields {
confirmDetails.WriteString(fmt.Sprintf(" * %s (%s): %s\n", field.FieldName, field.FieldType, field.FieldDesc)) confirmDetails.WriteString(fmt.Sprintf(" * %s (%s): %s\n", field.FieldName, field.FieldType, field.FieldDesc))
} }
} }
}
resultJSON, err := json.MarshalIndent(confirmResponse, "", " ") resultJSON, err := json.MarshalIndent(confirmResponse, "", " ")
if err != nil { if err != nil {
@ -1045,10 +1077,10 @@ func (t *AutomationModuleAnalyzer) buildDirectoryStructure(plan *ExecutionPlan)
packageName = plan.PackageInfo.PackageName packageName = plan.PackageInfo.PackageName
} }
// 如果计划中有模块信息,获取结构名 // 如果计划中有模块信息,获取第一个模块的结构名作为默认值
structName := "ExampleStruct" structName := "ExampleStruct"
if plan.ModulesInfo != nil && plan.ModulesInfo.StructName != "" { if len(plan.ModulesInfo) > 0 && plan.ModulesInfo[0].StructName != "" {
structName = plan.ModulesInfo.StructName structName = plan.ModulesInfo[0].StructName
} }
// 根据包类型构建不同的路径结构 // 根据包类型构建不同的路径结构
@ -1138,9 +1170,6 @@ func (t *AutomationModuleAnalyzer) validateExecutionPlan(plan *ExecutionPlan) er
if plan.PackageName == "" { if plan.PackageName == "" {
return errors.New("packageName 不能为空") return errors.New("packageName 不能为空")
} }
if plan.ModuleName == "" {
return errors.New("moduleName 不能为空")
}
if plan.PackageType != "package" && plan.PackageType != "plugin" { if plan.PackageType != "package" && plan.PackageType != "plugin" {
return errors.New("packageType 必须是 'package' 或 'plugin'") return errors.New("packageType 必须是 'package' 或 'plugin'")
} }
@ -1171,53 +1200,56 @@ func (t *AutomationModuleAnalyzer) validateExecutionPlan(plan *ExecutionPlan) er
} }
} }
// 验证模块信息 // 验证模块信息(批量验证)
if plan.NeedCreatedModules { if plan.NeedCreatedModules {
if plan.ModulesInfo == nil { if len(plan.ModulesInfo) == 0 {
return errors.New("当 needCreatedModules=true 时modulesInfo 不能为空") return errors.New("当 needCreatedModules=true 时modulesInfo 不能为空")
} }
if plan.ModulesInfo.Package == "" {
return errors.New("modulesInfo.package 不能为空") // 遍历验证每个模块
for moduleIndex, moduleInfo := range plan.ModulesInfo {
if moduleInfo.Package == "" {
return fmt.Errorf("模块 %d 的 package 不能为空", moduleIndex+1)
} }
if plan.ModulesInfo.StructName == "" { if moduleInfo.StructName == "" {
return errors.New("modulesInfo.structName 不能为空") return fmt.Errorf("模块 %d 的 structName 不能为空", moduleIndex+1)
} }
if plan.ModulesInfo.TableName == "" { if moduleInfo.TableName == "" {
return errors.New("modulesInfo.tableName 不能为空") return fmt.Errorf("模块 %d 的 tableName 不能为空", moduleIndex+1)
} }
if plan.ModulesInfo.Description == "" { if moduleInfo.Description == "" {
return errors.New("modulesInfo.description 不能为空") return fmt.Errorf("模块 %d 的 description 不能为空", moduleIndex+1)
} }
if plan.ModulesInfo.Abbreviation == "" { if moduleInfo.Abbreviation == "" {
return errors.New("modulesInfo.abbreviation 不能为空") return fmt.Errorf("模块 %d 的 abbreviation 不能为空", moduleIndex+1)
} }
if plan.ModulesInfo.PackageName == "" { if moduleInfo.PackageName == "" {
return errors.New("modulesInfo.packageName 不能为空") return fmt.Errorf("模块 %d 的 packageName 不能为空", moduleIndex+1)
} }
if plan.ModulesInfo.HumpPackageName == "" { if moduleInfo.HumpPackageName == "" {
return errors.New("modulesInfo.humpPackageName 不能为空") return fmt.Errorf("模块 %d 的 humpPackageName 不能为空", moduleIndex+1)
} }
// 验证字段信息 // 验证字段信息
if len(plan.ModulesInfo.Fields) == 0 { if len(moduleInfo.Fields) == 0 {
return errors.New("modulesInfo.fields 不能为空,至少需要一个字段") return fmt.Errorf("模块 %d 的 fields 不能为空,至少需要一个字段", moduleIndex+1)
} }
for i, field := range plan.ModulesInfo.Fields { for i, field := range moduleInfo.Fields {
if field.FieldName == "" { if field.FieldName == "" {
return fmt.Errorf("字段 %d 的 fieldName 不能为空", i+1) return fmt.Errorf("模块 %d 字段 %d 的 fieldName 不能为空", moduleIndex+1, i+1)
} }
if field.FieldDesc == "" { if field.FieldDesc == "" {
return fmt.Errorf("字段 %d 的 fieldDesc 不能为空", i+1) return fmt.Errorf("模块 %d 字段 %d 的 fieldDesc 不能为空", moduleIndex+1, i+1)
} }
if field.FieldType == "" { if field.FieldType == "" {
return fmt.Errorf("字段 %d 的 fieldType 不能为空", i+1) return fmt.Errorf("模块 %d 字段 %d 的 fieldType 不能为空", moduleIndex+1, i+1)
} }
if field.FieldJson == "" { if field.FieldJson == "" {
return fmt.Errorf("字段 %d 的 fieldJson 不能为空", i+1) return fmt.Errorf("模块 %d 字段 %d 的 fieldJson 不能为空", moduleIndex+1, i+1)
} }
if field.ColumnName == "" { if field.ColumnName == "" {
return fmt.Errorf("字段 %d 的 columnName 不能为空", i+1) return fmt.Errorf("模块 %d 字段 %d 的 columnName 不能为空", moduleIndex+1, i+1)
} }
// 验证字段类型 // 验证字段类型
@ -1230,7 +1262,7 @@ func (t *AutomationModuleAnalyzer) validateExecutionPlan(plan *ExecutionPlan) er
} }
} }
if !validType { if !validType {
return fmt.Errorf("字段 %d 的 fieldType '%s' 不支持,支持的类型:%v", i+1, field.FieldType, validFieldTypes) return fmt.Errorf("模块 %d 字段 %d 的 fieldType '%s' 不支持,支持的类型:%v", moduleIndex+1, i+1, field.FieldType, validFieldTypes)
} }
// 验证搜索类型(如果设置了) // 验证搜索类型(如果设置了)
@ -1244,31 +1276,32 @@ func (t *AutomationModuleAnalyzer) validateExecutionPlan(plan *ExecutionPlan) er
} }
} }
if !validSearchType { if !validSearchType {
return fmt.Errorf("字段 %d 的 fieldSearchType '%s' 不支持,支持的类型:%v", i+1, field.FieldSearchType, validSearchTypes) return fmt.Errorf("模块 %d 字段 %d 的 fieldSearchType '%s' 不支持,支持的类型:%v", moduleIndex+1, i+1, field.FieldSearchType, validSearchTypes)
} }
} }
} }
// 验证主键设置 // 验证主键设置
if !plan.ModulesInfo.GvaModel { if !moduleInfo.GvaModel {
// 当不使用GVA模型时必须有且仅有一个字段设置为主键 // 当不使用GVA模型时必须有且仅有一个字段设置为主键
primaryKeyCount := 0 primaryKeyCount := 0
for _, field := range plan.ModulesInfo.Fields { for _, field := range moduleInfo.Fields {
if field.PrimaryKey { if field.PrimaryKey {
primaryKeyCount++ primaryKeyCount++
} }
} }
if primaryKeyCount == 0 { if primaryKeyCount == 0 {
return errors.New("当 gvaModel=false 时,必须有一个字段的 primaryKey=true") return fmt.Errorf("模块 %d当 gvaModel=false 时,必须有一个字段的 primaryKey=true", moduleIndex+1)
} }
if primaryKeyCount > 1 { if primaryKeyCount > 1 {
return errors.New("当 gvaModel=false 时,只能有一个字段的 primaryKey=true") return fmt.Errorf("模块 %d当 gvaModel=false 时,只能有一个字段的 primaryKey=true", moduleIndex+1)
} }
} else { } else {
// 当使用GVA模型时所有字段的primaryKey都应该为false // 当使用GVA模型时所有字段的primaryKey都应该为false
for i, field := range plan.ModulesInfo.Fields { for i, field := range moduleInfo.Fields {
if field.PrimaryKey { if field.PrimaryKey {
return fmt.Errorf("当 gvaModel=true 时,字段 %d 的 primaryKey 应该为 false系统会自动创建ID主键", i+1) return fmt.Errorf("模块 %d当 gvaModel=true 时,字段 %d 的 primaryKey 应该为 false系统会自动创建ID主键", moduleIndex+1, i+1)
}
} }
} }
} }
@ -1305,30 +1338,33 @@ func (t *AutomationModuleAnalyzer) executeCreation(ctx context.Context, plan *Ex
result.Message += "包创建成功; " result.Message += "包创建成功; "
} }
// 创建字典(如果需要) // 批量创建字典和模块(如果需要)
if plan.NeedCreatedModules && plan.ModulesInfo != nil { if plan.NeedCreatedModules && len(plan.ModulesInfo) > 0 {
dictResult := t.createRequiredDictionaries(ctx, plan.ModulesInfo)
result.Message += dictResult
}
// 创建模块(如果需要)
if plan.NeedCreatedModules && plan.ModulesInfo != nil {
templateService := service.ServiceGroupApp.SystemServiceGroup.AutoCodeTemplate templateService := service.ServiceGroupApp.SystemServiceGroup.AutoCodeTemplate
err := plan.ModulesInfo.Pretreatment() // 先批量创建所有模块需要的字典
dictResult := t.createRequiredDictionaries(ctx, plan.ModulesInfo)
result.Message += dictResult
// 遍历所有模块进行创建
for _, moduleInfo := range plan.ModulesInfo {
// 创建模块
err := moduleInfo.Pretreatment()
if err != nil { if err != nil {
result.Message += fmt.Sprintf("模块信息预处理失败: %v", err) result.Message += fmt.Sprintf("模块 %s 信息预处理失败: %v; ", moduleInfo.StructName, err)
// 即使预处理失败也要返回paths信息 continue // 继续处理下一个模块
return result
} }
err = templateService.Create(ctx, *plan.ModulesInfo) err = templateService.Create(ctx, *moduleInfo)
if err != nil { if err != nil {
result.Message += fmt.Sprintf("创建模块失败: %v", err) result.Message += fmt.Sprintf("创建模块 %s 失败: %v; ", moduleInfo.StructName, err)
// 即使创建模块失败也要返回paths信息 continue // 继续处理下一个模块
return result
} }
result.Message += "模块创建成功; " result.Message += fmt.Sprintf("模块 %s 创建成功; ", moduleInfo.StructName)
}
result.Message += fmt.Sprintf("批量创建完成,共处理 %d 个模块; ", len(plan.ModulesInfo))
} }
result.Message += "已构建目录结构信息; " result.Message += "已构建目录结构信息; "
@ -1341,14 +1377,28 @@ func (t *AutomationModuleAnalyzer) executeCreation(ctx context.Context, plan *Ex
return result return result
} }
// createRequiredDictionaries 创建所需的字典 // createRequiredDictionaries 创建所需的字典(批量处理)
func (t *AutomationModuleAnalyzer) createRequiredDictionaries(ctx context.Context, modulesInfo *request.AutoCode) string { func (t *AutomationModuleAnalyzer) createRequiredDictionaries(ctx context.Context, modulesInfoList []*request.AutoCode) string {
var messages []string var messages []string
dictionaryService := service.ServiceGroupApp.SystemServiceGroup.DictionaryService dictionaryService := service.ServiceGroupApp.SystemServiceGroup.DictionaryService
createdDictTypes := make(map[string]bool) // 用于避免重复创建相同的字典
// 遍历所有字段,查找使用字典的字段 // 遍历所有模块
for moduleIndex, modulesInfo := range modulesInfoList {
messages = append(messages, fmt.Sprintf("处理模块 %d (%s) 的字典: ", moduleIndex+1, modulesInfo.StructName))
// 遍历当前模块的所有字段,查找使用字典的字段
moduleHasDictFields := false
for _, field := range modulesInfo.Fields { for _, field := range modulesInfo.Fields {
if field.DictType != "" { if field.DictType != "" {
moduleHasDictFields = true
// 如果这个字典类型已经在之前的模块中创建过,跳过
if createdDictTypes[field.DictType] {
messages = append(messages, fmt.Sprintf("字典 %s 已在前面的模块中创建,跳过; ", field.DictType))
continue
}
// 检查字典是否存在 // 检查字典是否存在
exists, err := t.checkDictionaryExists(field.DictType) exists, err := t.checkDictionaryExists(field.DictType)
if err != nil { if err != nil {
@ -1362,7 +1412,7 @@ func (t *AutomationModuleAnalyzer) createRequiredDictionaries(ctx context.Contex
Name: t.generateDictionaryName(field.DictType, field.FieldDesc), Name: t.generateDictionaryName(field.DictType, field.FieldDesc),
Type: field.DictType, Type: field.DictType,
Status: &[]bool{true}[0], // 默认启用 Status: &[]bool{true}[0], // 默认启用
Desc: fmt.Sprintf("自动生成的字典,用于字段: %s (%s)", field.FieldName, field.FieldDesc), Desc: fmt.Sprintf("自动生成的字典,用于模块 %s 字段: %s (%s)", modulesInfo.StructName, field.FieldName, field.FieldDesc),
} }
err = dictionaryService.CreateSysDictionary(dictionary) err = dictionaryService.CreateSysDictionary(dictionary)
@ -1370,16 +1420,23 @@ func (t *AutomationModuleAnalyzer) createRequiredDictionaries(ctx context.Contex
messages = append(messages, fmt.Sprintf("创建字典 %s 失败: %v; ", field.DictType, err)) messages = append(messages, fmt.Sprintf("创建字典 %s 失败: %v; ", field.DictType, err))
} else { } else {
messages = append(messages, fmt.Sprintf("成功创建字典 %s (%s); ", field.DictType, dictionary.Name)) messages = append(messages, fmt.Sprintf("成功创建字典 %s (%s); ", field.DictType, dictionary.Name))
createdDictTypes[field.DictType] = true // 标记为已创建
// 创建默认的字典详情项 // 创建默认的字典详情项
t.createDefaultDictionaryDetails(ctx, field.DictType, field.FieldDesc) t.createDefaultDictionaryDetails(ctx, field.DictType, field.FieldDesc)
} }
} else { } else {
messages = append(messages, fmt.Sprintf("字典 %s 已存在,跳过创建; ", field.DictType)) messages = append(messages, fmt.Sprintf("字典 %s 已存在,跳过创建; ", field.DictType))
createdDictTypes[field.DictType] = true // 标记为已存在
} }
} }
} }
if !moduleHasDictFields {
messages = append(messages, "无需创建字典; ")
}
}
if len(messages) == 0 { if len(messages) == 0 {
return "未发现需要创建的字典; " return "未发现需要创建的字典; "
} }

View File

@ -64,7 +64,7 @@ type MenuCreator struct{}
// New 创建菜单创建工具 // New 创建菜单创建工具
func (m *MenuCreator) New() mcp.Tool { func (m *MenuCreator) New() mcp.Tool {
return mcp.NewTool("create_menu", return mcp.NewTool("create_menu",
mcp.WithDescription("创建前端菜单记录,用于在生成前端页面时自动创建对应的菜单项只要前端有页面生成都需要调用此mcp。"), mcp.WithDescription("创建前端菜单记录,用于AI编辑器自动添加前端页面时自动创建对应的菜单项。注意使用gva_auto_generate创建的包和模块会自动创建菜单项无需调用此工具。仅在AI编辑器自动添加前端页面时使用。"),
mcp.WithNumber("parentId", mcp.WithNumber("parentId",
mcp.Description("父菜单ID0表示根菜单"), mcp.Description("父菜单ID0表示根菜单"),
mcp.DefaultNumber(0), mcp.DefaultNumber(0),

View File

@ -0,0 +1,137 @@
package mcpTool
import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/mark3labs/mcp-go/mcp"
)
func init() {
RegisterTool(&RequirementAnalyzer{})
}
type RequirementAnalyzer struct{}
// RequirementAnalysisRequest 需求分析请求
type RequirementAnalysisRequest struct {
UserRequirement string `json:"userRequirement"`
}
// RequirementAnalysisResponse 需求分析响应
type RequirementAnalysisResponse struct {
AIPrompt string `json:"aiPrompt"` // 给AI的提示词
}
// New 返回工具注册信息
func (t *RequirementAnalyzer) New() mcp.Tool {
return mcp.NewTool("requirement_analyzer",
mcp.WithDescription(`**🚀 需求分析工具 - 首选入口工具最高优先级**
** 重要提示这是所有MCP工具的首选入口请优先使用**
**🎯 核心职责**
将用户的自然语言需求转换为AI可理解的结构化提示词
**📋 工作流程**
1. 接收用户自然语言需求描述
2. 生成专业的AI提示词要求AI将需求梳理为清晰的逻辑步骤
- **1. 第一步功能描述**
- **2. 第二步功能描述**
- **3. 第三步功能描述**
- **...**
3. 指导后续使用 gva_auto_generate 工具进行代码生成
** 适用场景**
- 用户有新的业务需求需要开发
- 需要创建新的功能模块
- 想要快速搭建业务系统
- 需求描述比较模糊需要AI帮助梳理
** 不负责的事情**
- 不生成具体的包名和模块名交给 gva_auto_generate
- 不进行代码生成交给 gva_auto_generate
- 不创建数据库表结构交给 gva_auto_generate
**🔄 推荐工作流**
requirement_analyzer gva_auto_generate 其他辅助工具
`),
mcp.WithString("userRequirement",
mcp.Required(),
mcp.Description("用户的需求描述,支持自然语言,如:'我要做一个猫舍管理系统,用来录入猫的信息,并且记录每只猫每天的活动信息'"),
),
)
}
// Handle 处理工具调用
func (t *RequirementAnalyzer) Handle(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
userRequirement, ok := request.GetArguments()["userRequirement"].(string)
if !ok || userRequirement == "" {
return nil, errors.New("参数错误userRequirement 必须是非空字符串")
}
// 分析用户需求
analysisResponse, err := t.analyzeRequirement(userRequirement)
if err != nil {
return nil, fmt.Errorf("需求分析失败: %v", err)
}
// 序列化响应
responseData, err := json.Marshal(analysisResponse)
if err != nil {
return nil, fmt.Errorf("序列化响应失败: %v", err)
}
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.NewTextContent(string(responseData)),
},
}, nil
}
// analyzeRequirement 分析用户需求 - 专注于AI需求传递
func (t *RequirementAnalyzer) analyzeRequirement(userRequirement string) (*RequirementAnalysisResponse, error) {
// 生成AI提示词 - 这是唯一功能
aiPrompt := t.generateAIPrompt(userRequirement)
return &RequirementAnalysisResponse{
AIPrompt: aiPrompt,
}, nil
}
// generateAIPrompt 生成AI提示词 - 要求AI梳理逻辑为1xxx2xxx格式
func (t *RequirementAnalyzer) generateAIPrompt(userRequirement string) string {
prompt := fmt.Sprintf(`# 🤖 AI需求逻辑梳理任务
## 📝 用户原始需求
%s
## 🎯 AI任务要求
请将上述用户需求梳理成清晰的逻辑步骤格式要求
**1. 第一步功能描述**
**2. 第二步功能描述**
**3. 第三步功能描述**
**...**
## 📋 梳理要求
- 将需求拆解为具体的功能步骤
- 每个步骤用数字编号123...
- 步骤描述要清晰具体可执行
- 按照业务逻辑顺序排列
- 考虑数据流和用户操作流程
## 🔄 后续流程
梳理完成后请使用 gva_auto_generate 工具进行代码生成
- gva_auto_generate 会根据梳理的逻辑步骤自动生成包名模块名
- gva_auto_generate 会设计数据表结构和API接口
- gva_auto_generate 会生成完整的前后端代码
现在请开始梳理用户需求"%s"`, userRequirement, userRequirement)
return prompt
}

View File

@ -5,7 +5,7 @@ var (
ApiVerify = Rules{"Path": {NotEmpty()}, "Description": {NotEmpty()}, "ApiGroup": {NotEmpty()}, "Method": {NotEmpty()}} ApiVerify = Rules{"Path": {NotEmpty()}, "Description": {NotEmpty()}, "ApiGroup": {NotEmpty()}, "Method": {NotEmpty()}}
MenuVerify = Rules{"Path": {NotEmpty()}, "Name": {NotEmpty()}, "Component": {NotEmpty()}, "Sort": {Ge("0")}} MenuVerify = Rules{"Path": {NotEmpty()}, "Name": {NotEmpty()}, "Component": {NotEmpty()}, "Sort": {Ge("0")}}
MenuMetaVerify = Rules{"Title": {NotEmpty()}} MenuMetaVerify = Rules{"Title": {NotEmpty()}}
LoginVerify = Rules{"CaptchaId": {NotEmpty()}, "Username": {NotEmpty()}, "Password": {NotEmpty()}} LoginVerify = Rules{"CaptchaId": {NotEmpty()}, "Captcha": {NotEmpty()}, "Username": {NotEmpty()}, "Password": {NotEmpty()}}
RegisterVerify = Rules{"Username": {NotEmpty()}, "NickName": {NotEmpty()}, "Password": {NotEmpty()}, "AuthorityId": {NotEmpty()}} RegisterVerify = Rules{"Username": {NotEmpty()}, "NickName": {NotEmpty()}, "Password": {NotEmpty()}, "AuthorityId": {NotEmpty()}}
PageInfoVerify = Rules{"Page": {NotEmpty()}, "PageSize": {NotEmpty()}} PageInfoVerify = Rules{"Page": {NotEmpty()}, "PageSize": {NotEmpty()}}
CustomerVerify = Rules{"CustomerName": {NotEmpty()}, "CustomerPhoneData": {NotEmpty()}} CustomerVerify = Rules{"CustomerName": {NotEmpty()}, "CustomerPhoneData": {NotEmpty()}}