V2.8.4Beta 极致融合AI编辑器 让开发速度更进一步 (#2060)

* fix(style): 修复 border 额外的 reset 导致 tailwind border 属性生效异常的问题

* feat: 添加错误预览组件并优化请求错误处理逻辑

* optimize: select and update necessary fields in `ChangePassword` method

- Simplify `ChangePassword` method signature by removing unnecessary return type.
- Use `Select()` to fetch only the necessary fields (`id` and `password`) from the database.
- Replace `Save()` with `Update()` for more efficient password update operation.

Note: use `Save(&user)` to update the whole user record, which will cover other unchanged fields as well, causing data inconsistency when data race conditions.

* feat(menu): 版本更新为2.8.4,给菜单增加按钮和参数的预制打包

* feat(menu): 恢复空白的配置文件

* Remove unused `SideMode` field from `ChangeUserInfo` struct

Remove unused and deprecated `SideMode` field from user request model.

* feat(automation): 增加可以自动生成CURD和续写方法的MCP

* fix(mcp): 确保始终返回目录结构信息

* fix(mcp): 当不需要创建模块时提前返回目录结构信息

* feat(automation): 增加可以自动生成CURD和续写方法的MCP

* feat(mcp): 添加GAG工具用户确认流程和自动字典创建功能

实现三步工作流程:分析、确认、执行
新增自动字典创建功能,当字段使用字典类型时自动检查并创建字典
添加用户确认机制,确保创建操作前获得用户明确确认

* feat(version): 新增版本管理功能,支持创建、导入、导出和下载版本数据

新增版本管理模块,包含以下功能:
1. 版本数据的增删改查
2. 版本创建功能,可选择关联菜单和API
3. 版本导入导出功能
4. 版本JSON数据下载
5. 相关前端页面和接口实现

* refactor(version): 简化版本管理删除逻辑并移除无用字段

移除版本管理中的状态、创建者、更新者和删除者字段
简化删除和批量删除方法的实现,去除事务和用户ID参数
更新自动生成配置的默认值说明

* feat(版本管理): 新增版本管理功能模块

* fix(menu): 修复递归创建菜单时关联数据未正确处理的问题

* feat(mcp): 添加预设计模块扫描功能以支持代码自动生成

在自动化模块分析器中添加对预设计模块的扫描功能,包括:
- 新增PredesignedModuleInfo结构体存储模块信息
- 实现scanPredesignedModules方法扫描plugin和model目录
- 在分析响应中添加predesignedModules字段
- 更新帮助文档说明预设计模块的使用方式

这些修改使系统能够识别并利用现有的预设计模块,提高代码生成效率并减少重复工作。

* feat(mcp): 新增API、菜单和字典生成工具并优化自动生成模块

* docs(mcp): 更新菜单和API创建工具的描述信息

* feat(mcp): 添加字典查询工具用于AI生成逻辑时了解可用字典选项

* feat: 在创建菜单/API/模块结果中添加权限分配提醒

为菜单创建、API创建和模块创建的结果消息添加权限分配提醒,帮助用户了解后续需要进行的权限配置步骤

* refactor(mcp): 统一使用WithBoolean替换WithBool并优化错误处理

* docs(mcp): 更新API创建工具的说明和错误处理日志

* feat(mcp): 添加插件意图检测功能并增强验证逻辑

---------

Co-authored-by: Azir <2075125282@qq.com>
Co-authored-by: Feng.YJ <jxfengyijie@gmail.com>
Co-authored-by: piexlMax(奇淼 <qimiaojiangjizhao@gmail.com>
This commit is contained in:
PiexlMax(奇淼
2025-07-31 21:21:04 +08:00
committed by GitHub
parent 39abc7b632
commit 273d7bd50e
48 changed files with 4839 additions and 165 deletions

View File

@@ -0,0 +1,234 @@
package mcpTool
import (
"context"
"encoding/json"
"fmt"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
"github.com/flipped-aurora/gin-vue-admin/server/service"
"github.com/mark3labs/mcp-go/mcp"
"go.uber.org/zap"
"gorm.io/gorm"
)
// 注册工具
func init() {
RegisterTool(&DictionaryQuery{})
}
// DictionaryInfo 字典信息结构
type DictionaryInfo struct {
ID uint `json:"id"`
Name string `json:"name"` // 字典名(中)
Type string `json:"type"` // 字典名(英)
Status *bool `json:"status"` // 状态
Desc string `json:"desc"` // 描述
Details []DictionaryDetailInfo `json:"details"` // 字典详情
}
// DictionaryDetailInfo 字典详情信息结构
type DictionaryDetailInfo struct {
ID uint `json:"id"`
Label string `json:"label"` // 展示值
Value string `json:"value"` // 字典值
Extend string `json:"extend"` // 扩展值
Status *bool `json:"status"` // 启用状态
Sort int `json:"sort"` // 排序标记
}
// DictionaryQueryResponse 字典查询响应结构
type DictionaryQueryResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
Total int `json:"total"`
Dictionaries []DictionaryInfo `json:"dictionaries"`
}
// DictionaryQuery 字典查询工具
type DictionaryQuery struct{}
// New 创建字典查询工具
func (d *DictionaryQuery) New() mcp.Tool {
return mcp.NewTool("query_dictionaries",
mcp.WithDescription("查询系统中所有的字典和字典属性用于AI生成逻辑时了解可用的字典选项"),
mcp.WithString("dictType",
mcp.Description("可选:指定字典类型进行精确查询,如果不提供则返回所有字典"),
),
mcp.WithBoolean("includeDisabled",
mcp.Description("是否包含已禁用的字典和字典项默认为false只返回启用的"),
),
mcp.WithBoolean("detailsOnly",
mcp.Description("是否只返回字典详情信息不包含字典基本信息默认为false"),
),
)
}
// Handle 处理字典查询请求
func (d *DictionaryQuery) Handle(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
args := request.GetArguments()
// 获取参数
dictType := ""
if val, ok := args["dictType"].(string); ok {
dictType = val
}
includeDisabled := false
if val, ok := args["includeDisabled"].(bool); ok {
includeDisabled = val
}
detailsOnly := false
if val, ok := args["detailsOnly"].(bool); ok {
detailsOnly = val
}
// 获取字典服务
dictionaryService := service.ServiceGroupApp.SystemServiceGroup.DictionaryService
var dictionaries []DictionaryInfo
var err error
if dictType != "" {
// 查询指定类型的字典
var status *bool
if !includeDisabled {
status = &[]bool{true}[0]
}
sysDictionary, err := dictionaryService.GetSysDictionary(dictType, 0, status)
if err != nil {
global.GVA_LOG.Error("查询字典失败", zap.Error(err))
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.NewTextContent(fmt.Sprintf(`{"success": false, "message": "查询字典失败: %v", "total": 0, "dictionaries": []}`, err.Error())),
},
}, nil
}
// 转换为响应格式
dictInfo := DictionaryInfo{
ID: sysDictionary.ID,
Name: sysDictionary.Name,
Type: sysDictionary.Type,
Status: sysDictionary.Status,
Desc: sysDictionary.Desc,
}
// 获取字典详情
for _, detail := range sysDictionary.SysDictionaryDetails {
if includeDisabled || (detail.Status != nil && *detail.Status) {
dictInfo.Details = append(dictInfo.Details, DictionaryDetailInfo{
ID: detail.ID,
Label: detail.Label,
Value: detail.Value,
Extend: detail.Extend,
Status: detail.Status,
Sort: detail.Sort,
})
}
}
dictionaries = append(dictionaries, dictInfo)
} else {
// 查询所有字典
var sysDictionaries []system.SysDictionary
db := global.GVA_DB.Model(&system.SysDictionary{})
if !includeDisabled {
db = db.Where("status = ?", true)
}
err = db.Preload("SysDictionaryDetails", func(db *gorm.DB) *gorm.DB {
if includeDisabled {
return db.Order("sort")
} else {
return db.Where("status = ?", true).Order("sort")
}
}).Find(&sysDictionaries).Error
if err != nil {
global.GVA_LOG.Error("查询字典列表失败", zap.Error(err))
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.NewTextContent(fmt.Sprintf(`{"success": false, "message": "查询字典列表失败: %v", "total": 0, "dictionaries": []}`, err.Error())),
},
}, nil
}
// 转换为响应格式
for _, dict := range sysDictionaries {
dictInfo := DictionaryInfo{
ID: dict.ID,
Name: dict.Name,
Type: dict.Type,
Status: dict.Status,
Desc: dict.Desc,
}
// 获取字典详情
for _, detail := range dict.SysDictionaryDetails {
if includeDisabled || (detail.Status != nil && *detail.Status) {
dictInfo.Details = append(dictInfo.Details, DictionaryDetailInfo{
ID: detail.ID,
Label: detail.Label,
Value: detail.Value,
Extend: detail.Extend,
Status: detail.Status,
Sort: detail.Sort,
})
}
}
dictionaries = append(dictionaries, dictInfo)
}
}
// 如果只需要详情信息,则提取所有详情
if detailsOnly {
var allDetails []DictionaryDetailInfo
for _, dict := range dictionaries {
allDetails = append(allDetails, dict.Details...)
}
response := map[string]interface{}{
"success": true,
"message": "查询字典详情成功",
"total": len(allDetails),
"details": allDetails,
}
responseJSON, _ := json.Marshal(response)
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.NewTextContent(string(responseJSON)),
},
}, nil
}
// 构建响应
response := DictionaryQueryResponse{
Success: true,
Message: "查询字典成功",
Total: len(dictionaries),
Dictionaries: dictionaries,
}
responseJSON, err := json.Marshal(response)
if err != nil {
global.GVA_LOG.Error("序列化响应失败", zap.Error(err))
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.NewTextContent(fmt.Sprintf(`{"success": false, "message": "序列化响应失败: %v", "total": 0, "dictionaries": []}`, err.Error())),
},
}, nil
}
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.NewTextContent(string(responseJSON)),
},
}, nil
}