Files
gin-vue-admin-stu/server/mcp/dictionary_generator.go
PiexlMax(奇淼 7d3e7b5b7a public:发布2.8.6版本 (#2126)
* feat(mcp): 新增gva_review工具并优化字典和代码生成逻辑

* fix: 调整mcp整体逻辑

* chore: 更新.gitignore,添加对本地配置文件的忽略

* feat(logo): 新增Logo组件并在多个页面中替换原有logo实现

* fix: 修复菜单 Logo 部分删除文本后显示异常的问题

* fix:添加字典列表搜索,支持中英文搜索.添加字典详情搜索

* style: 优化部分视觉样式

* feat: 增强错误预览组件的暗黑模式支持

* feat: 优化请求错误消息获取逻辑,增加状态文本优先级

* feat: 添加前端登录验证码静态验证逻辑

* feat: 添加开发环境启动脚本

* feat: 更新 SvgIcon 组件,支持本地图标和 Iconify 图标、移除未使用的 unocss 依赖

* fix:字典支持 tree 结构

* feat: 优化动态路由注册方式

* feat: 添加配置控制标签页keep-alive功能

* feat: 添加全局错误处理机制,捕获 Vue 和 JS 错误

* refactor: 移除API和菜单创建结果中的权限分配提醒,优化输出信息

* feat: 更新 reset.scss,优化全局样式重置,增强兼容性和可读性

* refactor(字典详情): 优化字典详情查询逻辑,移除预加载改为按需加载

* refactor(路由管理): 优化路由添加逻辑,增强路径处理和顶级路由注册

* refactor(系统配置): 将auto-migrate修改为disable-auto-migrate,保证用户升级的兼容性

* feat(utils): 优化字典数据递归查找功能并替换select为tree-select

* fix(deps): 修复在字段类型为file生成搜索条件无法运行的bug

* fix: 修复header的tools中icon不展示的问题

---------

Co-authored-by: piexlMax(奇淼 <qimiaojiangjizhao@gmail.com>
Co-authored-by: Azir-11 <2075125282@qq.com>
Co-authored-by: bypanghu <bypanghu@163.com>
Co-authored-by: feitianbubu <feitianbubu@qq.com>
Co-authored-by: 青菜白玉汤 <79054161+Azir-11@users.noreply.github.com>
Co-authored-by: krank <emosick@qq.com>
2025-10-19 13:27:48 +08:00

317 lines
9.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package mcpTool
import (
"context"
"encoding/json"
"errors"
"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(&DictionaryOptionsGenerator{})
}
// DictionaryOptionsGenerator 字典选项生成器
type DictionaryOptionsGenerator struct{}
// DictionaryOption 字典选项结构
type DictionaryOption struct {
Label string `json:"label"`
Value string `json:"value"`
Sort int `json:"sort"`
}
// DictionaryGenerateRequest 字典生成请求
type DictionaryGenerateRequest struct {
DictType string `json:"dictType"` // 字典类型
FieldDesc string `json:"fieldDesc"` // 字段描述
Options []DictionaryOption `json:"options"` // AI生成的字典选项
DictName string `json:"dictName"` // 字典名称(可选)
Description string `json:"description"` // 字典描述(可选)
}
// DictionaryGenerateResponse 字典生成响应
type DictionaryGenerateResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
DictType string `json:"dictType"`
OptionsCount int `json:"optionsCount"`
}
// New 返回工具注册信息
func (d *DictionaryOptionsGenerator) New() mcp.Tool {
return mcp.NewTool("generate_dictionary_options",
mcp.WithDescription("智能生成字典选项并自动创建字典和字典详情"),
mcp.WithString("dictType",
mcp.Required(),
mcp.Description("字典类型,用于标识字典的唯一性"),
),
mcp.WithString("fieldDesc",
mcp.Required(),
mcp.Description("字段描述用于AI理解字段含义"),
),
mcp.WithString("options",
mcp.Required(),
mcp.Description("字典选项JSON字符串格式[{\"label\":\"显示名\",\"value\":\"值\",\"sort\":1}]"),
),
mcp.WithString("dictName",
mcp.Description("字典名称,如果不提供将自动生成"),
),
mcp.WithString("description",
mcp.Description("字典描述"),
),
)
}
// Name 返回工具名称
func (d *DictionaryOptionsGenerator) Name() string {
return "generate_dictionary_options"
}
// Description 返回工具描述
func (d *DictionaryOptionsGenerator) Description() string {
return `字典选项生成工具 - 让AI生成并创建字典选项
此工具允许AI根据字典类型和字段描述生成合适的字典选项并自动创建字典和字典详情。
参数说明:
- dictType: 字典类型(必填)
- fieldDesc: 字段描述(必填)
- options: AI生成的字典选项数组必填
- label: 选项标签
- value: 选项值
- sort: 排序号
- dictName: 字典名称可选默认根据fieldDesc生成
- description: 字典描述(可选)
使用场景:
1. 在创建模块时如果字段需要字典类型AI可以根据字段描述智能生成合适的选项
2. 支持各种业务场景的字典选项生成,如状态、类型、等级等
3. 自动创建字典和字典详情,无需手动配置
示例调用:
{
"dictType": "user_status",
"fieldDesc": "用户状态",
"options": [
{"label": "正常", "value": "1", "sort": 1},
{"label": "禁用", "value": "0", "sort": 2}
],
"dictName": "用户状态字典",
"description": "用于管理用户账户状态的字典"
}`
}
// InputSchema 返回输入参数的JSON Schema
func (d *DictionaryOptionsGenerator) InputSchema() map[string]interface{} {
return map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"dictType": map[string]interface{}{
"type": "string",
"description": "字典类型,用于标识字典的唯一性",
},
"fieldDesc": map[string]interface{}{
"type": "string",
"description": "字段描述,用于生成字典名称和理解字典用途",
},
"options": map[string]interface{}{
"type": "array",
"description": "AI生成的字典选项数组",
"items": map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"label": map[string]interface{}{
"type": "string",
"description": "选项标签,显示给用户的文本",
},
"value": map[string]interface{}{
"type": "string",
"description": "选项值,存储在数据库中的值",
},
"sort": map[string]interface{}{
"type": "integer",
"description": "排序号,用于控制选项显示顺序",
},
},
"required": []string{"label", "value", "sort"},
},
},
"dictName": map[string]interface{}{
"type": "string",
"description": "字典名称必填默认根据fieldDesc生成",
},
"description": map[string]interface{}{
"type": "string",
"description": "字典描述,必填",
},
},
"required": []string{"dictType", "fieldDesc", "options"},
}
}
// Handle 处理工具调用
func (d *DictionaryOptionsGenerator) Handle(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
// 解析请求参数
args := request.GetArguments()
dictType, ok := args["dictType"].(string)
if !ok || dictType == "" {
return nil, errors.New("dictType 参数是必需的")
}
fieldDesc, ok := args["fieldDesc"].(string)
if !ok || fieldDesc == "" {
return nil, errors.New("fieldDesc 参数是必需的")
}
optionsStr, ok := args["options"].(string)
if !ok || optionsStr == "" {
return nil, errors.New("options 参数是必需的")
}
// 解析options JSON字符串
var options []DictionaryOption
if err := json.Unmarshal([]byte(optionsStr), &options); err != nil {
return nil, fmt.Errorf("options 参数格式错误: %v", err)
}
if len(options) == 0 {
return nil, errors.New("options 不能为空")
}
dictName, _ := args["dictName"].(string)
description, _ := args["description"].(string)
// 构建请求对象
req := &DictionaryGenerateRequest{
DictType: dictType,
FieldDesc: fieldDesc,
Options: options,
DictName: dictName,
Description: description,
}
// 创建字典
response, err := d.createDictionaryWithOptions(ctx, req)
if err != nil {
return nil, err
}
// 构建响应
resultJSON, err := json.MarshalIndent(response, "", " ")
if err != nil {
return nil, fmt.Errorf("序列化结果失败: %v", err)
}
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf("字典选项生成结果:\n\n%s", string(resultJSON)),
},
},
}, nil
}
// createDictionaryWithOptions 创建字典和字典选项
func (d *DictionaryOptionsGenerator) createDictionaryWithOptions(ctx context.Context, req *DictionaryGenerateRequest) (*DictionaryGenerateResponse, error) {
// 检查字典是否已存在
exists, err := d.checkDictionaryExists(req.DictType)
if err != nil {
return nil, fmt.Errorf("检查字典是否存在失败: %v", err)
}
if exists {
return &DictionaryGenerateResponse{
Success: false,
Message: fmt.Sprintf("字典 %s 已存在,跳过创建", req.DictType),
DictType: req.DictType,
OptionsCount: 0,
}, nil
}
// 生成字典名称
dictName := req.DictName
if dictName == "" {
dictName = d.generateDictionaryName(req.DictType, req.FieldDesc)
}
// 创建字典
dictionaryService := service.ServiceGroupApp.SystemServiceGroup.DictionaryService
dictionary := system.SysDictionary{
Name: dictName,
Type: req.DictType,
Status: &[]bool{true}[0], // 默认启用
Desc: req.Description,
}
err = dictionaryService.CreateSysDictionary(dictionary)
if err != nil {
return nil, fmt.Errorf("创建字典失败: %v", err)
}
// 获取刚创建的字典ID
var createdDict system.SysDictionary
err = global.GVA_DB.Where("type = ?", req.DictType).First(&createdDict).Error
if err != nil {
return nil, fmt.Errorf("获取创建的字典失败: %v", err)
}
// 创建字典详情项
dictionaryDetailService := service.ServiceGroupApp.SystemServiceGroup.DictionaryDetailService
successCount := 0
for _, option := range req.Options {
dictionaryDetail := system.SysDictionaryDetail{
Label: option.Label,
Value: option.Value,
Status: &[]bool{true}[0], // 默认启用
Sort: option.Sort,
SysDictionaryID: int(createdDict.ID),
}
err = dictionaryDetailService.CreateSysDictionaryDetail(dictionaryDetail)
if err != nil {
global.GVA_LOG.Warn("创建字典详情项失败", zap.Error(err))
} else {
successCount++
}
}
return &DictionaryGenerateResponse{
Success: true,
Message: fmt.Sprintf("成功创建字典 %s包含 %d 个选项", req.DictType, successCount),
DictType: req.DictType,
OptionsCount: successCount,
}, nil
}
// checkDictionaryExists 检查字典是否存在
func (d *DictionaryOptionsGenerator) checkDictionaryExists(dictType string) (bool, error) {
var dictionary system.SysDictionary
err := global.GVA_DB.Where("type = ?", dictType).First(&dictionary).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return false, nil // 字典不存在
}
return false, err // 其他错误
}
return true, nil // 字典存在
}
// generateDictionaryName 生成字典名称
func (d *DictionaryOptionsGenerator) generateDictionaryName(dictType, fieldDesc string) string {
if fieldDesc != "" {
return fmt.Sprintf("%s字典", fieldDesc)
}
return fmt.Sprintf("%s字典", dictType)
}