Compare commits

...

10 Commits

Author SHA1 Message Date
PiexlMax(奇淼
1d700ad5b6 Update README.md
Some checks failed
CI / init (push) Has been cancelled
CI / Frontend node 18.16.0 (push) Has been cancelled
CI / Backend go (1.22) (push) Has been cancelled
CI / release-pr (push) Has been cancelled
CI / devops-test (1.22, 18.16.0) (push) Has been cancelled
CI / release-please (push) Has been cancelled
CI / devops-prod (1.22, 18.x) (push) Has been cancelled
CI / docker (push) Has been cancelled
2025-08-19 18:26:17 +08:00
PiexlMax(奇淼
3648df9522 Merge pull request #2070 from dzwvip/main
修改gorm-oracle的驱动包为go-ora,不再依赖cgo和oracle instant  client
2025-08-14 15:33:51 +08:00
dzwvip
eb2925829f 修改gorm-oracle的驱动包为go-ora,不再依赖cgo和oracle client 2025-08-12 15:05:38 +08:00
piexlMax(奇淼
1e3c968277 refactor(mcp): 更新默认值描述并移除无用工具 2025-08-11 10:52:15 +08:00
piexlMax(奇淼
339db778c3 chore: 优化引入svg方式 2025-08-08 11:46:08 +08:00
piexlMax(奇淼
8b8ae7b692 refactor(auth): 简化权限指令中的类型检查逻辑 2025-08-07 16:18:04 +08:00
piexlMax(奇淼
52be26eb43 fix: 修正未配置默认路由时的错误提示信息 2025-08-06 15:55:38 +08:00
piexlMax(奇淼
9f958addc8 fix(verify): 移除登录验证中的Captcha字段校验
refactor(validation): 强制字段名首字母大写并更新文档
2025-08-06 15:18:03 +08:00
piexlMax(奇淼
7a69b88885 refactor(config): 更新配置文件格式并添加新配置项 2025-08-06 13:47:09 +08:00
pixelmaxQM
76fe71a8dd docs(mcp): 完善工具描述并添加重要限制说明 2025-08-05 20:35:12 +08:00
14 changed files with 267 additions and 353 deletions

View File

@@ -22,7 +22,8 @@
<table> <table>
<tr> <tr>
<td width="200"> <td width="250">
<p>⭐️ <a href="https://www.bilibili.com/video/BV1B3htzqEf1/?spm_id_from=333.1387.homepage.video_card.click" target="__blank"> 高度适配AI编辑器的MCP </a></p>
<p>📄 创建基础模板</p> <p>📄 创建基础模板</p>
<p>🤖 AI生成结构</p> <p>🤖 AI生成结构</p>
<p>⏰ 生成代码</p> <p>⏰ 生成代码</p>

View File

@@ -2,107 +2,103 @@
# jwt configuration # jwt configuration
jwt: jwt:
signing-key: qmPlus signing-key: qmPlus
expires-time: 7d expires-time: 7d
buffer-time: 1d buffer-time: 1d
issuer: qmPlus issuer: qmPlus
# zap logger configuration # zap logger configuration
zap: zap:
level: info level: info
format: console format: console
prefix: "[github.com/flipped-aurora/gin-vue-admin/server]" prefix: "[github.com/flipped-aurora/gin-vue-admin/server]"
director: log director: log
show-line: true show-line: true
encode-level: LowercaseColorLevelEncoder encode-level: LowercaseColorLevelEncoder
stacktrace-key: stacktrace stacktrace-key: stacktrace
log-in-console: true log-in-console: true
retention-day: -1
# redis configuration # redis configuration
redis: redis:
db: 0 #是否使用redis集群模式
addr: 177.7.0.14:6379 useCluster: false
password: "" #使用集群模式addr和db默认无效
addr: 177.7.0.14:6379
password: ""
db: 0
clusterAddrs:
- "177.7.0.14:7000"
- "177.7.0.15:7001"
- "177.7.0.13:7002"
# redis-list configuration
redis-list:
- name: cache # 数据库的名称,注意: name 需要在 redis-list 中唯一
useCluster: false # 是否使用redis集群模式
addr: 177.7.0.14:6379 # 使用集群模式addr和db默认无效
password: ""
db: 0
clusterAddrs:
- "177.7.0.14:7000"
- "177.7.0.15:7001"
- "177.7.0.13:7002"
# mongo configuration # mongo configuration
mongo: mongo:
coll: '' coll: ''
options: '' options: ''
database: '' database: ''
username: '' username: ''
password: '' password: ''
min-pool-size: 0 auth-source: ''
max-pool-size: 100 min-pool-size: 0
socket-timeout-ms: 0 max-pool-size: 100
connect-timeout-ms: 0 socket-timeout-ms: 0
is-zap: false connect-timeout-ms: 0
hosts: is-zap: false
- host: '' hosts:
port: '' - host: ''
port: ''
# email configuration # email configuration
email: email:
to: xxx@qq.com to: xxx@qq.com
port: 465 port: 465
from: xxx@163.com from: xxx@163.com
host: smtp.163.com host: smtp.163.com
is-ssl: true is-ssl: true
secret: xxx secret: xxx
nickname: test nickname: test
# system configuration # system configuration
system: system:
env: public # Change to "develop" to skip authentication for development mode env: local # 修改为public可以关闭路由日志输出
addr: 8888 addr: 8888
db-type: mysql db-type: mysql
oss-type: local # 控制oss选择走本地还是 七牛等其他仓 自行增加其他oss仓可以在 server/utils/upload/upload.go 中 NewOss函数配置 oss-type: local # 控制oss选择走本地还是 七牛等其他仓 自行增加其他oss仓可以在 server/utils/upload/upload.go 中 NewOss函数配置
use-redis: false # 使用redis use-redis: false # 使用redis
use-mongo: false # 使用mongo use-mongo: false # 使用mongo
use-multipoint: false use-multipoint: false
# IP限制次数 一个小时15000次 # IP限制次数 一个小时15000次
iplimit-count: 15000 iplimit-count: 15000
# IP限制一个小时 # IP限制一个小时
iplimit-time: 3600 iplimit-time: 3600
# 路由全局前缀
router-prefix: ""
# 严格角色模式 打开后权限将会存在上下级关系
use-strict-auth: false
# captcha configuration # captcha configuration
captcha: captcha:
key-long: 6 key-long: 6
img-width: 240 img-width: 240
img-height: 80 img-height: 80
open-captcha: 0 # 0代表一直开启大于0代表限制次数 open-captcha: 0 # 0代表一直开启大于0代表限制次数
open-captcha-timeout: 3600 # open-captcha大于0时才生效 open-captcha-timeout: 3600 # open-captcha大于0时才生效
# mysql connect configuration # mysql connect configuration
# 未初始化之前请勿手动修改数据库信息如果一定要手动初始化请看https://gin-vue-admin.com/docs/first_master # 未初始化之前请勿手动修改数据库信息如果一定要手动初始化请看https://gin-vue-admin.com/docs/first_master
mysql: mysql:
path: ""
port: ""
config: ""
db-name: ""
username: ""
password: ""
max-idle-conns: 10
max-open-conns: 100
log-mode: ""
log-zap: false
# pgsql connect configuration
# 未初始化之前请勿手动修改数据库信息如果一定要手动初始化请看https://gin-vue-admin.com/docs/first_master
pgsql:
path: ""
port: ""
config: ""
db-name: ""
username: ""
password: ""
max-idle-conns: 10
max-open-conns: 100
log-mode: ""
log-zap: false
db-list:
- disable: true # 是否禁用
type: "" # 数据库的类型,目前支持mysql、pgsql
alias-name: "" # 数据库的名称,注意: alias-name 需要在db-list中唯一
path: "" path: ""
port: "" port: ""
config: "" config: ""
@@ -114,107 +110,174 @@ db-list:
log-mode: "" log-mode: ""
log-zap: false log-zap: false
# pgsql connect configuration
# 未初始化之前请勿手动修改数据库信息如果一定要手动初始化请看https://gin-vue-admin.com/docs/first_master
pgsql:
path: ""
port: ""
config: ""
db-name: ""
username: ""
password: ""
max-idle-conns: 10
max-open-conns: 100
log-mode: ""
log-zap: false
oracle:
path: ""
port: ""
config: ""
db-name: ""
username: ""
password: ""
max-idle-conns: 10
max-open-conns: 100
log-mode: ""
log-zap: false
mssql:
path: ""
port: ""
config: ""
db-name: ""
username: ""
password: ""
max-idle-conns: 10
max-open-conns: 100
log-mode: ""
log-zap: false
sqlite:
path: ""
port: ""
config: ""
db-name: ""
username: ""
password: ""
max-idle-conns: 10
max-open-conns: 100
log-mode: ""
log-zap: false
db-list:
- disable: true # 是否禁用
type: "" # 数据库的类型,目前支持mysql、pgsql、mssql、oracle
alias-name: "" # 数据库的名称,注意: alias-name 需要在db-list中唯一
path: ""
port: ""
config: ""
db-name: ""
username: ""
password: ""
max-idle-conns: 10
max-open-conns: 100
log-mode: ""
log-zap: false
# local configuration # local configuration
local: local:
path: uploads/file path: uploads/file
store-path: uploads/file store-path: uploads/file
# autocode configuration # autocode configuration
autocode: autocode:
transfer-restart: true web: web/src
# root 自动适配项目根目录 root: "" # root 自动适配项目根目录, 请不要手动配置,他会在项目加载的时候识别出根路径
# 请不要手动配置,他会在项目加载的时候识别出根路径 server: server
root: "" module: 'github.com/flipped-aurora/gin-vue-admin/server'
server: /server ai-path: "" # AI服务路径
server-plug: /plugin/%s
server-api: /api/v1/%s
server-initialize: /initialize
server-model: /model/%s
server-request: /model/%s/request/
server-router: /router/%s
server-service: /service/%s
web: /web/src
web-api: /api
web-form: /view
web-table: /view
# qiniu configuration (请自行七牛申请对应的 公钥 私钥 bucket 和 域名地址) # qiniu configuration (请自行七牛申请对应的 公钥 私钥 bucket 和 域名地址)
qiniu: qiniu:
zone: ZoneHuaDong zone: ZoneHuaDong
bucket: "" bucket: ""
img-path: "" img-path: ""
use-https: false use-https: false
access-key: "" access-key: ""
secret-key: "" secret-key: ""
use-cdn-domains: false use-cdn-domains: false
# minio oss configuration
minio:
endpoint: yourEndpoint
access-key-id: yourAccessKeyId
access-key-secret: yourAccessKeySecret
bucket-name: yourBucketName
use-ssl: false
base-path: ""
bucket-url: "http://host:9000/yourBucketName"
# aliyun oss configuration # aliyun oss configuration
aliyun-oss: aliyun-oss:
endpoint: yourEndpoint endpoint: yourEndpoint
access-key-id: yourAccessKeyId access-key-id: yourAccessKeyId
access-key-secret: yourAccessKeySecret access-key-secret: yourAccessKeySecret
bucket-name: yourBucketName bucket-name: yourBucketName
bucket-url: yourBucketUrl bucket-url: yourBucketUrl
base-path: yourBasePath base-path: yourBasePath
# tencent cos configuration # tencent cos configuration
tencent-cos: tencent-cos:
bucket: xxxxx-10005608 bucket: xxxxx-10005608
region: ap-shanghai region: ap-shanghai
secret-id: your-secret-id secret-id: your-secret-id
secret-key: your-secret-key secret-key: your-secret-key
base-url: https://gin.vue.admin base-url: https://gin.vue.admin
path-prefix: github.com/flipped-aurora/gin-vue-admin/server path-prefix: github.com/flipped-aurora/gin-vue-admin/server
# aws s3 configuration (minio compatible) # aws s3 configuration (minio compatible)
aws-s3: aws-s3:
bucket: xxxxx-10005608 bucket: xxxxx-10005608
region: ap-shanghai region: ap-shanghai
endpoint: "" endpoint: ""
s3-force-path-style: false s3-force-path-style: false
disable-ssl: false disable-ssl: false
secret-id: your-secret-id secret-id: your-secret-id
secret-key: your-secret-key secret-key: your-secret-key
base-url: https://gin.vue.admin base-url: https://gin.vue.admin
path-prefix: github.com/flipped-aurora/gin-vue-admin/server path-prefix: github.com/flipped-aurora/gin-vue-admin/server
# cloudflare r2 configuration
cloudflare-r2:
bucket: xxxx0bucket
base-url: https://gin.vue.admin.com
path: uploads
account-id: xxx_account_id
access-key-id: xxx_key_id
secret-access-key: xxx_secret_key
# huawei obs configuration # huawei obs configuration
hua-wei-obs: hua-wei-obs:
path: you-path path: you-path
bucket: you-bucket bucket: you-bucket
endpoint: you-endpoint endpoint: you-endpoint
access-key: you-access-key access-key: you-access-key
secret-key: you-secret-key secret-key: you-secret-key
# excel configuration # excel configuration
excel: excel:
dir: ./resource/excel/ dir: ./resource/excel/
# timer task db clear table # disk usage configuration
Timer: disk-list:
start: true - mount-point: "/"
spec: "@daily" # 定时任务详细配置参考 https://pkg.go.dev/github.com/robfig/cron/v3
detail:
- tableName: sys_operation_records
compareField: created_at
interval: 2160h
- tableName: jwt_blacklists
compareField: created_at
interval: 168h
# 跨域配置 # 跨域配置
# 需要配合 server/initialize/router.go -> `Router.Use(middleware.CorsByRules())` 使用 # 需要配合 server/initialize/router.go -> `Router.Use(middleware.CorsByRules())` 使用
cors: cors:
mode: whitelist # 放行模式: allow-all, 放行全部; whitelist, 白名单模式, 来自白名单内域名的请求添加 cors 头; strict-whitelist 严格白名单模式, 白名单外的请求一律拒绝 mode: strict-whitelist # 放行模式: allow-all, 放行全部; whitelist, 白名单模式, 来自白名单内域名的请求添加 cors 头; strict-whitelist 严格白名单模式, 白名单外的请求一律拒绝
whitelist: whitelist:
- allow-origin: example1.com - allow-origin: example1.com
allow-headers: content-type allow-headers: Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id
allow-methods: GET, POST allow-methods: POST, GET
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type
allow-credentials: true # 布尔值
- allow-origin: example2.com allow-credentials: true # 布尔值
allow-headers: content-type - allow-origin: example2.com
allow-methods: GET, POST allow-headers: content-type
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type allow-methods: GET, POST
allow-credentials: true # 布尔值 expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type
allow-credentials: true # 布尔值
mcp:
name: GVA_MCP
version: v1.0.0
sse_path: /sse
message_path: /message
url_prefix: ''

View File

@@ -1,10 +1,18 @@
package config package config
import (
"fmt"
"net"
"net/url"
)
type Oracle struct { type Oracle struct {
GeneralDB `yaml:",inline" mapstructure:",squash"` GeneralDB `yaml:",inline" mapstructure:",squash"`
} }
func (m *Oracle) Dsn() string { func (m *Oracle) Dsn() string {
return "oracle://" + m.Username + ":" + m.Password + "@" + m.Path + ":" + m.Port + "/" + m.Dbname + "?" + m.Config dsn := fmt.Sprintf("oracle://%s:%s@%s/%s?%s", url.PathEscape(m.Username), url.PathEscape(m.Password),
net.JoinHostPort(m.Path, m.Port), url.PathEscape(m.Dbname), m.Config)
return dsn
} }

View File

@@ -1,18 +1,14 @@
package initialize package initialize
import ( import (
//"github.com/dzwvip/oracle" oracle "github.com/dzwvip/gorm-oracle"
"github.com/flipped-aurora/gin-vue-admin/server/config" "github.com/flipped-aurora/gin-vue-admin/server/config"
"github.com/flipped-aurora/gin-vue-admin/server/global" "github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/initialize/internal" "github.com/flipped-aurora/gin-vue-admin/server/initialize/internal"
//_ "github.com/godror/godror"
"gorm.io/driver/mysql"
"gorm.io/gorm" "gorm.io/gorm"
) )
// GormOracle 初始化oracle数据库 // GormOracle 初始化oracle数据库
// 如果需要Oracle库 放开import里的注释 把下方 mysql.Config 改为 oracle.Config ; mysql.New 改为 oracle.New
func GormOracle() *gorm.DB { func GormOracle() *gorm.DB {
m := global.GVA_CONFIG.Oracle m := global.GVA_CONFIG.Oracle
return initOracleDatabase(m) return initOracleDatabase(m)
@@ -28,13 +24,7 @@ func initOracleDatabase(m config.Oracle) *gorm.DB {
if m.Dbname == "" { if m.Dbname == "" {
return nil return nil
} }
if db, err := gorm.Open(oracle.Open(m.Dsn()), internal.Gorm.Config(m.Prefix, m.Singular)); err != nil {
oracleConfig := mysql.Config{
DSN: m.Dsn(), // DSN data source name
DefaultStringSize: 191, // string 类型字段的默认长度
}
if db, err := gorm.Open(mysql.New(oracleConfig), internal.Gorm.Config(m.Prefix, m.Singular)); err != nil {
panic(err) panic(err)
} else { } else {
sqlDB, _ := db.DB() sqlDB, _ := db.DB()

View File

@@ -41,7 +41,11 @@ 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记录用于AI编辑器自动添加API接口时自动创建对应的API权限记录。注意使用gva_auto_generate创建的包和模块会自动创建API权限无需调用此工具。仅在AI编辑器自动添加API或router下的文件产生路径变化时使用。"), mcp.WithDescription(`创建后端API记录用于AI编辑器自动添加API接口时自动创建对应的API权限记录。
**重要限制:**
- 当使用gva_auto_generate工具且needCreatedModules=true时模块创建会自动生成API权限不应调用此工具
- 仅在以下情况使用1) 单独创建API不涉及模块创建2) AI编辑器自动添加API3) router下的文件产生路径变化时`),
mcp.WithString("path", mcp.WithString("path",
mcp.Required(), mcp.Required(),
mcp.Description("API路径/user/create"), mcp.Description("API路径/user/create"),

View File

@@ -1,81 +0,0 @@
package mcpTool
import (
"context"
"errors"
"fmt"
"github.com/mark3labs/mcp-go/mcp"
"time"
)
func init() {
RegisterTool(&CurrentTime{})
}
type CurrentTime struct {
}
// 获取当前系统时间
func (t *CurrentTime) Handle(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
// 获取当前系统时间
timezone, ok := request.GetArguments()["timezone"].(string)
if !ok {
return nil, errors.New("参数错误timezone 必须是字符串类型")
}
// 根据timezone参数加载对应时区
loc, err := loadTimeZone(timezone)
if err != nil {
return nil, err
}
// 获取当前时间并转换为指定时区
currentTime := time.Now().In(loc).Format("2006-01-02 15:04:05")
//返回
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf("%s 时区的当前时间是:%s", timezone, currentTime),
},
},
}, nil
}
func (t *CurrentTime) New() mcp.Tool {
return mcp.NewTool("currentTime",
mcp.WithDescription("获取当前系统时间"),
mcp.WithString("timezone",
mcp.Required(),
mcp.Description("时区"),
mcp.Enum("UTC", "CST", "PST", "EST", "GMT", "CET", "JST", "MST", "IST", "AST", "HST"),
))
}
// 将简写时区转换为IANA标准时区
func loadTimeZone(timezone string) (*time.Location, error) {
// 时区映射表
timezoneMap := map[string]string{
"UTC": "UTC",
"CST": "Asia/Shanghai", // 中国标准时间
"PST": "America/Los_Angeles",
"EST": "America/New_York",
"GMT": "GMT",
"CET": "Europe/Paris",
"JST": "Asia/Tokyo",
"MST": "America/Denver",
"IST": "Asia/Kolkata",
"AST": "Asia/Riyadh", // 阿拉伯标准时间
"HST": "Pacific/Honolulu",
}
// 获取标准时区名称
tzName, exists := timezoneMap[timezone]
if !exists {
return nil, errors.New("不支持的时区: " + timezone)
}
// 加载时区
return time.LoadLocation(tzName)
}

View File

@@ -1,79 +0,0 @@
package mcpTool
import (
"context"
"errors"
"fmt"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
"github.com/mark3labs/mcp-go/mcp"
"gorm.io/gorm"
)
func init() {
RegisterTool(&GetNickname{})
}
type GetNickname struct{}
// 根据用户username获取nickname
func (t *GetNickname) New() mcp.Tool {
return mcp.NewTool("getNickname",
mcp.WithDescription("根据用户username获取nickname"),
mcp.WithString("username",
mcp.Required(),
mcp.Description("用户的username"),
))
}
// Handle 处理获取昵称的请求
func (t *GetNickname) Handle(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
// 1. 参数验证
username, ok := request.GetArguments()["username"].(string)
if !ok {
return nil, errors.New("参数错误username 必须是字符串类型")
}
if username == "" {
return nil, errors.New("参数错误username 不能为空")
}
// 2. 记录操作日志
global.GVA_LOG.Info("getNickname 工具被调用")
// 3. 优化查询,只选择需要的字段
var user struct {
NickName string
}
err := global.GVA_DB.Model(&system.SysUser{}).
Select("nick_name").
Where("username = ?", username).
First(&user).Error
// 4. 优化错误处理
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf("用户 %s 不存在", username),
},
},
}, nil
}
global.GVA_LOG.Error("数据库查询错误")
return nil, errors.New("系统错误,请稍后再试")
}
// 构造回复信息
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf("用户 %s 的昵称是 %s", username, user.NickName),
},
},
}, nil
}

View File

@@ -135,6 +135,10 @@ func (t *AutomationModuleAnalyzer) New() mcp.Tool {
2. AI分析需求为1xxx2xxx格式 → gva_auto_generate执行创建 2. AI分析需求为1xxx2xxx格式 → gva_auto_generate执行创建
3. 创建完成后,根据需要使用其他辅助工具 3. 创建完成后,根据需要使用其他辅助工具
**重要限制:**
- 当needCreatedModules=true时模块创建会自动生成API和菜单因此不应再调用api_creator和menu_creator工具
- 只有在单独创建API或菜单不涉及模块创建时才使用api_creator和menu_creator工具
重要ExecutionPlan结构体格式要求支持批量创建 重要ExecutionPlan结构体格式要求支持批量创建
{ {
"packageName": "包名(string)", "packageName": "包名(string)",
@@ -169,7 +173,7 @@ func (t *AutomationModuleAnalyzer) New() mcp.Tool {
"generateWeb": "是否生成前端(bool)", "generateWeb": "是否生成前端(bool)",
"generateServer": "是否生成后端(bool)", "generateServer": "是否生成后端(bool)",
"fields": [{ "fields": [{
"fieldName": "字段名(string)", "fieldName": "字段名(string)必须大写开头",
"fieldDesc": "字段描述(string)", "fieldDesc": "字段描述(string)",
"fieldType": "字段类型支持string字符串,richtext富文本,int整型,bool布尔值,float64浮点型,time.Time时间,enum枚举,picture单图片字符串,pictures多图片json字符串,video视频字符串,file文件json字符串,jsonJSON,array数组", "fieldType": "字段类型支持string字符串,richtext富文本,int整型,bool布尔值,float64浮点型,time.Time时间,enum枚举,picture单图片字符串,pictures多图片json字符串,video视频字符串,file文件json字符串,jsonJSON,array数组",
"fieldJson": "JSON标签(string)", "fieldJson": "JSON标签(string)",
@@ -184,7 +188,7 @@ func (t *AutomationModuleAnalyzer) New() mcp.Tool {
"desc": "详情显示(bool)", "desc": "详情显示(bool)",
"excel": "导入导出(bool)", "excel": "导入导出(bool)",
"require": "是否必填(bool)", "require": "是否必填(bool)",
"defaultValue": "默认值(string)", "defaultValue": "默认值(string)JSON类型array,json,file,pictures请保持为空他们不可以设置默认值",
"errorText": "错误提示(string)", "errorText": "错误提示(string)",
"clearable": "是否可清空(bool)", "clearable": "是否可清空(bool)",
"sort": "是否排序(bool)", "sort": "是否排序(bool)",
@@ -1239,6 +1243,14 @@ func (t *AutomationModuleAnalyzer) validateExecutionPlan(plan *ExecutionPlan) er
if field.FieldName == "" { if field.FieldName == "" {
return fmt.Errorf("模块 %d 字段 %d 的 fieldName 不能为空", moduleIndex+1, i+1) return fmt.Errorf("模块 %d 字段 %d 的 fieldName 不能为空", moduleIndex+1, i+1)
} }
// 确保字段名首字母大写
if len(field.FieldName) > 0 {
firstChar := string(field.FieldName[0])
if firstChar >= "a" && firstChar <= "z" {
moduleInfo.Fields[i].FieldName = strings.ToUpper(firstChar) + field.FieldName[1:]
}
}
if field.FieldDesc == "" { if field.FieldDesc == "" {
return fmt.Errorf("模块 %d 字段 %d 的 fieldDesc 不能为空", moduleIndex+1, i+1) return fmt.Errorf("模块 %d 字段 %d 的 fieldDesc 不能为空", moduleIndex+1, i+1)
} }
@@ -1365,6 +1377,13 @@ func (t *AutomationModuleAnalyzer) executeCreation(ctx context.Context, plan *Ex
} }
result.Message += fmt.Sprintf("批量创建完成,共处理 %d 个模块; ", len(plan.ModulesInfo)) result.Message += fmt.Sprintf("批量创建完成,共处理 %d 个模块; ", len(plan.ModulesInfo))
// 添加重要提醒不要使用其他MCP工具
result.Message += "\n\n⚠ 重要提醒:\n"
result.Message += "模块创建已完成API和菜单已自动生成。请不要再调用以下MCP工具\n"
result.Message += "- api_creatorAPI权限已在模块创建时自动生成\n"
result.Message += "- menu_creator前端菜单已在模块创建时自动生成\n"
result.Message += "如需修改API或菜单请直接在系统管理界面中进行配置。\n"
} }
result.Message += "已构建目录结构信息; " result.Message += "已构建目录结构信息; "

View File

@@ -64,7 +64,11 @@ 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("创建前端菜单记录用于AI编辑器自动添加前端页面时自动创建对应的菜单项。注意使用gva_auto_generate创建的包和模块会自动创建菜单项无需调用此工具。仅在AI编辑器自动添加前端页面时使用。"), mcp.WithDescription(`创建前端菜单记录用于AI编辑器自动添加前端页面时自动创建对应的菜单项。
**重要限制:**
- 当使用gva_auto_generate工具且needCreatedModules=true时模块创建会自动生成菜单项不应调用此工具
- 仅在以下情况使用1) 单独创建菜单不涉及模块创建2) AI编辑器自动添加前端页面时`),
mcp.WithNumber("parentId", mcp.WithNumber("parentId",
mcp.Description("父菜单ID0表示根菜单"), mcp.Description("父菜单ID0表示根菜单"),
mcp.DefaultNumber(0), mcp.DefaultNumber(0),

View File

@@ -64,7 +64,7 @@ WHERE
lower(a.table_name) = ? lower(a.table_name) = ?
AND lower(a.OWNER) = ? AND lower(a.OWNER) = ?
ORDER BY ORDER BY
a.COLUMN_ID; a.COLUMN_ID
` `
err = global.GVA_DBList[businessDB].Raw(sql, tableName, dbName).Scan(&entities).Error err = global.GVA_DBList[businessDB].Raw(sql, tableName, dbName).Scan(&entities).Error

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()}, "Captcha": {NotEmpty()}, "Username": {NotEmpty()}, "Password": {NotEmpty()}} LoginVerify = Rules{"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()}}

View File

@@ -42,7 +42,7 @@
"tailwindcss": "^3.4.10", "tailwindcss": "^3.4.10",
"universal-cookie": "^7", "universal-cookie": "^7",
"vform3-builds": "^3.0.10", "vform3-builds": "^3.0.10",
"vite-auto-import-svg": "^1.6.0", "vite-auto-import-svg": "^1.7.0",
"vue": "^3.5.7", "vue": "^3.5.7",
"vue-cropper": "^1.1.4", "vue-cropper": "^1.1.4",
"vue-echarts": "^7.0.3", "vue-echarts": "^7.0.3",

View File

@@ -7,22 +7,7 @@ export default {
// 当被绑定的元素插入到 DOM 中时…… // 当被绑定的元素插入到 DOM 中时……
mounted: function (el, binding) { mounted: function (el, binding) {
const userInfo = userStore.userInfo const userInfo = userStore.userInfo
let type = '' if (!binding.value){
switch (Object.prototype.toString.call(binding.value)) {
case '[object Array]':
type = 'Array'
break
case '[object String]':
type = 'String'
break
case '[object Number]':
type = 'Number'
break
default:
type = ''
break
}
if (type === '') {
el.parentNode.removeChild(el) el.parentNode.removeChild(el)
return return
} }

View File

@@ -93,7 +93,7 @@ export const useUserStore = defineStore('user', () => {
} }
if (!router.hasRoute(userInfo.value.authority.defaultRouter)) { if (!router.hasRoute(userInfo.value.authority.defaultRouter)) {
ElMessage.error('请联系管理员进行授权') ElMessage.error('不存在可以登陆的首页,请联系管理员进行配置')
} else { } else {
await router.replace({ name: userInfo.value.authority.defaultRouter }) await router.replace({ name: userInfo.value.authority.defaultRouter })
} }