@ -91,6 +91,10 @@ func NewServiceContext(c config.Config) *ServiceContext {
seedMenus ( db )
seedRoleMenus ( db )
// 种子 AI 供应商和模型
seedAIProviders ( db )
seedAIModels ( db )
// 初始化存储
store , err := storage . NewStorage ( c . Storage )
if err != nil {
@ -261,6 +265,16 @@ func seedCasbinPolicies(enforcer *casbin.Enforcer) {
// super_admin: 机构删除
{ "super_admin" , "/api/v1/organization/:id" , "DELETE" } ,
// AI: all authenticated users
{ "user" , "/api/v1/ai/chat/completions" , "POST" } ,
{ "user" , "/api/v1/ai/conversations" , "GET" } ,
{ "user" , "/api/v1/ai/conversation" , "POST" } ,
{ "user" , "/api/v1/ai/conversation/:id" , "GET" } ,
{ "user" , "/api/v1/ai/conversation/:id" , "PUT" } ,
{ "user" , "/api/v1/ai/conversation/:id" , "DELETE" } ,
{ "user" , "/api/v1/ai/models" , "GET" } ,
{ "user" , "/api/v1/ai/quota/me" , "GET" } ,
}
for _ , p := range policies {
@ -298,10 +312,11 @@ func seedMenus(db *gorm.DB) {
{ Name : "仪表盘" , Path : "/dashboard" , Icon : "LayoutDashboard" , Type : "config" , SortOrder : 2 , Visible : true , Status : 1 } ,
{ Name : "用户管理" , Path : "/users" , Icon : "Users" , Type : "config" , SortOrder : 3 , Visible : true , Status : 1 } ,
{ Name : "文件管理" , Path : "/files" , Icon : "FolderOpen" , Type : "config" , SortOrder : 4 , Visible : true , Status : 1 } ,
{ Name : "角色管理" , Path : "/roles" , Icon : "Shield" , Type : "config" , SortOrder : 5 , Visible : true , Status : 1 } ,
{ Name : "菜单管理" , Path : "/menus" , Icon : "Menu" , Type : "config" , SortOrder : 6 , Visible : true , Status : 1 } ,
{ Name : "机构管理" , Path : "/organizations" , Icon : "Building2" , Type : "config" , SortOrder : 7 , Visible : true , Status : 1 } ,
{ Name : "设置" , Path : "/settings" , Icon : "Settings" , Type : "default" , SortOrder : 8 , Visible : true , Status : 1 } ,
{ Name : "AI 对话" , Path : "/ai/chat" , Icon : "Bot" , Type : "config" , SortOrder : 5 , Visible : true , Status : 1 } ,
{ Name : "角色管理" , Path : "/roles" , Icon : "Shield" , Type : "config" , SortOrder : 6 , Visible : true , Status : 1 } ,
{ Name : "菜单管理" , Path : "/menus" , Icon : "Menu" , Type : "config" , SortOrder : 7 , Visible : true , Status : 1 } ,
{ Name : "机构管理" , Path : "/organizations" , Icon : "Building2" , Type : "config" , SortOrder : 8 , Visible : true , Status : 1 } ,
{ Name : "设置" , Path : "/settings" , Icon : "Settings" , Type : "default" , SortOrder : 9 , Visible : true , Status : 1 } ,
}
for _ , m := range menus {
@ -363,3 +378,51 @@ func seedRoleMenus(db *gorm.DB) {
}
log . Println ( "[Seed] RoleMenus seeded successfully" )
}
// seedAIProviders 种子 AI 供应商(幂等)
func seedAIProviders ( db * gorm . DB ) {
providers := [ ] model . AIProvider {
{ Name : "openai" , DisplayName : "OpenAI" , BaseUrl : "https://api.openai.com/v1" , SdkType : "openai_compat" , Protocol : "openai" , IsActive : true , SortOrder : 1 } ,
{ Name : "claude" , DisplayName : "Anthropic Claude" , BaseUrl : "https://api.anthropic.com" , SdkType : "anthropic" , Protocol : "anthropic" , IsActive : true , SortOrder : 2 } ,
{ Name : "qwen" , DisplayName : "阿里千问" , BaseUrl : "https://dashscope.aliyuncs.com/compatible-mode/v1" , SdkType : "openai_compat" , Protocol : "openai" , IsActive : true , SortOrder : 3 } ,
{ Name : "zhipu" , DisplayName : "智谱 GLM" , BaseUrl : "https://open.bigmodel.cn/api/paas/v4" , SdkType : "openai_compat" , Protocol : "openai" , IsActive : true , SortOrder : 4 } ,
{ Name : "deepseek" , DisplayName : "DeepSeek" , BaseUrl : "https://api.deepseek.com/v1" , SdkType : "openai_compat" , Protocol : "openai" , IsActive : true , SortOrder : 5 } ,
}
for _ , p := range providers {
var existing model . AIProvider
if err := db . Where ( "name = ?" , p . Name ) . First ( & existing ) . Error ; err != nil {
db . Create ( & p )
}
}
log . Println ( "[Seed] AI providers seeded successfully" )
}
// seedAIModels 种子 AI 模型(幂等)
func seedAIModels ( db * gorm . DB ) {
// First, fetch providers by name to get their IDs
providerIds := map [ string ] int64 { }
var providers [ ] model . AIProvider
db . Find ( & providers )
for _ , p := range providers {
providerIds [ p . Name ] = p . Id
}
models := [ ] model . AIModel {
{ ProviderId : providerIds [ "openai" ] , ModelId : "gpt-4o" , DisplayName : "GPT-4o" , InputPrice : 0.0025 , OutputPrice : 0.01 , MaxTokens : 16384 , ContextWindow : 128000 , SupportsStream : true , SupportsVision : true , IsActive : true , SortOrder : 1 } ,
{ ProviderId : providerIds [ "openai" ] , ModelId : "gpt-4o-mini" , DisplayName : "GPT-4o Mini" , InputPrice : 0.00015 , OutputPrice : 0.0006 , MaxTokens : 16384 , ContextWindow : 128000 , SupportsStream : true , SupportsVision : true , IsActive : true , SortOrder : 2 } ,
{ ProviderId : providerIds [ "claude" ] , ModelId : "claude-sonnet-4-5-20250514" , DisplayName : "Claude Sonnet 4.5" , InputPrice : 0.003 , OutputPrice : 0.015 , MaxTokens : 8192 , ContextWindow : 200000 , SupportsStream : true , SupportsVision : true , IsActive : true , SortOrder : 3 } ,
{ ProviderId : providerIds [ "claude" ] , ModelId : "claude-haiku-3-5-20241022" , DisplayName : "Claude Haiku 3.5" , InputPrice : 0.0008 , OutputPrice : 0.004 , MaxTokens : 8192 , ContextWindow : 200000 , SupportsStream : true , SupportsVision : true , IsActive : true , SortOrder : 4 } ,
{ ProviderId : providerIds [ "qwen" ] , ModelId : "qwen-plus" , DisplayName : "通义千问 Plus" , InputPrice : 0.0008 , OutputPrice : 0.002 , MaxTokens : 8192 , ContextWindow : 131072 , SupportsStream : true , SupportsVision : false , IsActive : true , SortOrder : 5 } ,
{ ProviderId : providerIds [ "qwen" ] , ModelId : "qwen-turbo" , DisplayName : "通义千问 Turbo" , InputPrice : 0.0003 , OutputPrice : 0.0006 , MaxTokens : 8192 , ContextWindow : 131072 , SupportsStream : true , SupportsVision : false , IsActive : true , SortOrder : 6 } ,
{ ProviderId : providerIds [ "zhipu" ] , ModelId : "glm-4-flash" , DisplayName : "GLM-4 Flash" , InputPrice : 0.0001 , OutputPrice : 0.0001 , MaxTokens : 4096 , ContextWindow : 128000 , SupportsStream : true , SupportsVision : false , IsActive : true , SortOrder : 7 } ,
{ ProviderId : providerIds [ "deepseek" ] , ModelId : "deepseek-chat" , DisplayName : "DeepSeek Chat" , InputPrice : 0.00014 , OutputPrice : 0.00028 , MaxTokens : 8192 , ContextWindow : 64000 , SupportsStream : true , SupportsVision : false , IsActive : true , SortOrder : 8 } ,
{ ProviderId : providerIds [ "deepseek" ] , ModelId : "deepseek-reasoner" , DisplayName : "DeepSeek Reasoner" , InputPrice : 0.00055 , OutputPrice : 0.00219 , MaxTokens : 8192 , ContextWindow : 64000 , SupportsStream : true , SupportsVision : false , IsActive : true , SortOrder : 9 } ,
}
for _ , m := range models {
var existing model . AIModel
if err := db . Where ( "model_id = ?" , m . ModelId ) . First ( & existing ) . Error ; err != nil {
db . Create ( & m )
}
}
log . Println ( "[Seed] AI models seeded successfully" )
}