🎉 初始化项目

Signed-off-by: Echo <1711788888@qq.com>
This commit is contained in:
2026-02-27 21:52:00 +08:00
commit f4e166c5ee
482 changed files with 55079 additions and 0 deletions

213
server/model/app/README.md Normal file
View File

@@ -0,0 +1,213 @@
# App 前台应用数据模型
## 📋 模型列表
本目录包含所有前台用户应用相关的数据模型,与管理后台的 `system` 模块完全独立。
### 1. 用户相关模型
| 文件 | 模型 | 表名 | 说明 |
|------|------|------|------|
| `app_user.go` | `AppUser` | `app_users` | 前台用户表 |
| `app_user_session.go` | `AppUserSession` | `app_user_sessions` | 用户会话表 |
### 2. AI 角色相关模型
| 文件 | 模型 | 表名 | 说明 |
|------|------|------|------|
| `ai_character.go` | `AICharacter` | `ai_characters` | AI 角色表 |
| `ai_character.go` | `AppUserFavoriteCharacter` | `app_user_favorite_characters` | 用户收藏角色表 |
### 3. 对话相关模型
| 文件 | 模型 | 表名 | 说明 |
|------|------|------|------|
| `ai_chat.go` | `AIChat` | `ai_chats` | 对话表 |
| `ai_chat.go` | `AIChatMember` | `ai_chat_members` | 群聊成员表 |
| `ai_message.go` | `AIMessage` | `ai_messages` | 消息表 |
| `ai_message.go` | `AIMessageSwipe` | `ai_message_swipes` | 消息变体表 |
### 4. 向量记忆模型
| 文件 | 模型 | 表名 | 说明 |
|------|------|------|------|
| `ai_memory.go` | `AIMemoryVector` | `ai_memory_vectors` | 向量记忆表(使用 pgvector |
### 5. AI 服务配置模型
| 文件 | 模型 | 表名 | 说明 |
|------|------|------|------|
| `ai_provider.go` | `AIProvider` | `ai_providers` | AI 提供商配置表 |
| `ai_provider.go` | `AIModel` | `ai_models` | AI 模型配置表 |
### 6. 文件管理模型
| 文件 | 模型 | 表名 | 说明 |
|------|------|------|------|
| `ai_file.go` | `AIFile` | `ai_files` | 文件表 |
### 7. 其他模型
| 文件 | 模型 | 表名 | 说明 |
|------|------|------|------|
| `ai_preset.go` | `AIPreset` | `ai_presets` | 对话预设表 |
| `ai_world_info.go` | `AIWorldInfo` | `ai_world_info` | 世界书表 |
| `ai_usage_stat.go` | `AIUsageStat` | `ai_usage_stats` | 使用统计表 |
## 🔧 使用说明
### 1. 数据库自动迁移
所有模型已在 `initialize/gorm.go` 中注册,启动服务时会自动创建表:
```go
// 在 RegisterTables() 函数中已注册
app.AppUser{},
app.AppUserSession{},
app.AICharacter{},
app.AppUserFavoriteCharacter{},
app.AIChat{},
app.AIChatMember{},
app.AIMessage{},
app.AIMessageSwipe{},
app.AIMemoryVector{},
app.AIProvider{},
app.AIModel{},
app.AIFile{},
app.AIPreset{},
app.AIWorldInfo{},
app.AIUsageStat{},
```
### 2. PostgreSQL 向量扩展
向量记忆功能依赖 `pgvector` 扩展,已在 `initialize/gorm_pgsql_extension.go` 中自动安装:
```sql
CREATE EXTENSION IF NOT EXISTS vector;
CREATE INDEX idx_memory_vectors_embedding ON ai_memory_vectors
USING hnsw (embedding vector_cosine_ops);
```
### 3. 外键关系
模型之间的关系已通过 GORM 标签定义:
- `AppUser``AppUserSession`(一对多)
- `AppUser``AICharacter`(一对多,创建者)
- `AppUser``AIChat`(一对多)
- `AppUser``AppUserFavoriteCharacter`(多对多,通过中间表)
- `AICharacter``AppUserFavoriteCharacter`(多对多,通过中间表)
- `AICharacter``AIChat`(一对多)
- `AIChat``AIMessage`(一对多)
- `AIChat``AIChatMember`(多对多,通过中间表)
- `AICharacter``AIChatMember`(多对多,通过中间表)
- `AIMessage``AIMessageSwipe`(一对多)
- `AIProvider``AIModel`(一对多)
### 4. JSONB 字段
以下字段使用 PostgreSQL 的 JSONB 类型:
- `AppUser.AISettings` - AI 相关配置
- `AppUser.Preferences` - 用户偏好设置
- `AICharacter.CardData` - 角色卡片数据
- `AICharacter.Tags` - 角色标签
- `AICharacter.ExampleMessages` - 消息示例
- `AIChat.Settings` - 对话设置
- `AIMessage.GenerationParams` - AI 生成参数
- `AIMessage.Metadata` - 消息元数据
- `AIMemoryVector.Metadata` - 记忆元数据
- `AIProvider.APIConfig` - API 配置
- `AIModel.Config` - 模型配置
- `AIFile.RelatedTo` - 文件关联对象
- `AIFile.Metadata` - 文件元数据
- `AIPreset.Config` - 预设配置
- `AIWorldInfo.TriggerConfig` - 触发条件配置
### 5. 向量字段
`AIMemoryVector.Embedding` 使用 `pgvector.Vector` 类型,维度为 1536OpenAI text-embedding-ada-002
## ⚠️ 注意事项
1. **不要修改 system 包**:所有管理后台相关的模型在 `model/system/` 包中,**不要修改**
2. **表名前缀**
- 前台用户相关:`app_*`
- AI 功能相关:`ai_*`
- 系统管理相关:`sys_*`(不修改)
3. **UUID 生成**`AppUser.UUID` 使用数据库自动生成PostgreSQL 的 `gen_random_uuid()`
4. **软删除**:所有模型继承 `global.GVA_MODEL`,自动支持软删除
5. **时间字段**`CreatedAt``UpdatedAt``DeletedAt` 由 GORM 自动管理
## 📊 ER 图关系
```
AppUser (前台用户)
├── AppUserSession (会话)
├── AICharacter (创建的角色)
├── AIChat (对话)
├── AppUserFavoriteCharacter (收藏的角色)
├── AIMemoryVector (记忆)
├── AIProvider (AI 提供商配置)
├── AIFile (文件)
├── AIPreset (预设)
├── AIWorldInfo (世界书)
└── AIUsageStat (使用统计)
AICharacter (AI 角色)
├── AIChat (对话)
├── AIChatMember (群聊成员)
├── AppUserFavoriteCharacter (被收藏)
└── AIMemoryVector (记忆)
AIChat (对话)
├── AIMessage (消息)
├── AIChatMember (群聊成员)
└── AIMemoryVector (记忆)
AIMessage (消息)
└── AIMessageSwipe (消息变体)
AIProvider (AI 提供商)
└── AIModel (AI 模型)
```
## 🚀 快速开始
1. 确保 PostgreSQL 已安装 pgvector 扩展
2. 配置 `config.yaml` 中的数据库连接
3. 启动服务AutoMigrate 会自动创建所有表
4. 检查日志确认表创建成功
```bash
# 启动服务
go run main.go
# 查看日志
# [GVA] pgvector extension is ready
# [GVA] vector indexes created successfully
# [GVA] register table success
```
## 📝 开发建议
1. 查询时使用预加载避免 N+1 问题:
```go
db.Preload("User").Preload("Character").Find(&chats)
```
2. 向量搜索示例:
```go
db.Order("embedding <=> ?", queryVector).Limit(10).Find(&memories)
```
3. JSONB 查询示例:
```go
db.Where("ai_settings->>'model' = ?", "gpt-4").Find(&users)
```
---
**创建日期**: 2026-02-10
**维护者**: 开发团队

View File

@@ -0,0 +1,49 @@
package app
import (
"time"
"gorm.io/datatypes"
"gorm.io/gorm"
)
// AICharacter 角色卡模型
type AICharacter struct {
ID uint `gorm:"primarykey" json:"id"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
// 基本信息
UserID uint `gorm:"index;not null" json:"userId"` // 所属用户ID
Name string `gorm:"type:varchar(100);not null" json:"name"` // 角色名称
Avatar string `gorm:"type:text" json:"avatar"` // 头像URL或Base64
Creator string `gorm:"type:varchar(100)" json:"creator"` // 创建者
Version string `gorm:"type:varchar(50)" json:"version"` // 角色版本
IsPublic bool `gorm:"default:false" json:"isPublic"` // 是否公开
// SillyTavern V2 格式字段
Description string `gorm:"type:text" json:"description"` // 角色描述
Personality string `gorm:"type:text" json:"personality"` // 性格特征
Scenario string `gorm:"type:text" json:"scenario"` // 场景设定
FirstMes string `gorm:"type:text" json:"firstMes"` // 第一条消息
MesExample string `gorm:"type:text" json:"mesExample"` // 消息示例
CreatorNotes string `gorm:"type:text" json:"creatorNotes"` // 创建者备注
SystemPrompt string `gorm:"type:text" json:"systemPrompt"` // 系统提示词
PostHistoryInstructions string `gorm:"type:text" json:"postHistoryInstructions"` // 历史后指令
Tags datatypes.JSON `gorm:"type:jsonb" json:"tags"` // 标签数组
AlternateGreetings datatypes.JSON `gorm:"type:jsonb" json:"alternateGreetings"` // 备用问候语
CharacterBook datatypes.JSON `gorm:"type:jsonb" json:"characterBook"` // 角色书
Extensions datatypes.JSON `gorm:"type:jsonb" json:"extensions"` // 扩展数据
Spec string `gorm:"type:varchar(50);default:'chara_card_v2'" json:"spec"` // 规范名称
SpecVersion string `gorm:"type:varchar(50);default:'2.0'" json:"specVersion"` // 规范版本
// 统计信息
UseCount int `gorm:"default:0" json:"useCount"` // 使用次数
FavoriteCount int `gorm:"default:0" json:"favoriteCount"` // 收藏次数
}
// TableName 指定表名
func (AICharacter) TableName() string {
return "ai_characters"
}

View File

@@ -0,0 +1,31 @@
package app
import (
"time"
"gorm.io/datatypes"
"gorm.io/gorm"
)
// AIConfig AI配置模型
type AIConfig struct {
ID uint `gorm:"primarykey" json:"id"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
Name string `gorm:"type:varchar(100);not null" json:"name"` // 配置名称
Provider string `gorm:"type:varchar(50);not null" json:"provider"` // 提供商 (openai/anthropic/custom)
BaseURL string `gorm:"type:varchar(500)" json:"baseUrl"` // API Base URL
APIKey string `gorm:"type:varchar(500)" json:"apiKey"` // API Key (加密存储)
Models datatypes.JSON `gorm:"type:jsonb" json:"models"` // 可用模型列表
DefaultModel string `gorm:"type:varchar(100)" json:"defaultModel"` // 默认模型
Settings datatypes.JSON `gorm:"type:jsonb" json:"settings"` // 其他设置 (temperature等)
IsActive bool `gorm:"default:false" json:"isActive"` // 是否激活
IsDefault bool `gorm:"default:false" json:"isDefault"` // 是否为默认配置
}
// TableName 指定表名
func (AIConfig) TableName() string {
return "ai_configs"
}

View File

@@ -0,0 +1,33 @@
package app
import (
"time"
"git.echol.cn/loser/st/server/global"
"gorm.io/datatypes"
)
// AppUser 前台用户模型(与 sys_users 独立)
type AppUser struct {
global.GVA_MODEL
UUID string `json:"uuid" gorm:"type:uuid;uniqueIndex;comment:用户UUID"`
Username string `json:"username" gorm:"uniqueIndex;comment:用户登录名"`
Password string `json:"-" gorm:"comment:用户登录密码"`
NickName string `json:"nickName" gorm:"comment:用户昵称"`
Email string `json:"email" gorm:"index;comment:用户邮箱"`
Phone string `json:"phone" gorm:"comment:用户手机号"`
Avatar string `json:"avatar" gorm:"type:varchar(1024);comment:用户头像"`
Status string `json:"status" gorm:"type:varchar(50);default:active;comment:账户状态"`
Enable bool `json:"enable" gorm:"default:true;comment:用户是否启用"`
IsAdmin bool `json:"isAdmin" gorm:"default:false;comment:是否为管理员"`
LastLoginAt *time.Time `json:"lastLoginAt" gorm:"comment:最后登录时间"`
LastLoginIP string `json:"lastLoginIp" gorm:"type:varchar(100);comment:最后登录IP"`
AISettings datatypes.JSON `json:"aiSettings" gorm:"type:jsonb;comment:AI配置"`
Preferences datatypes.JSON `json:"preferences" gorm:"type:jsonb;comment:用户偏好"`
ChatCount int `json:"chatCount" gorm:"default:0;comment:对话数量"`
MessageCount int `json:"messageCount" gorm:"default:0;comment:消息数量"`
}
func (AppUser) TableName() string {
return "app_users"
}

View File

@@ -0,0 +1,25 @@
package app
import (
"time"
"git.echol.cn/loser/st/server/global"
"gorm.io/datatypes"
)
// AppUserSession 前台用户会话
type AppUserSession struct {
global.GVA_MODEL
UserID uint `json:"userId" gorm:"index;comment:用户ID"`
SessionToken string `json:"sessionToken" gorm:"type:varchar(500);uniqueIndex;comment:会话Token"`
RefreshToken string `json:"refreshToken" gorm:"type:varchar(500);comment:刷新Token"`
ExpiresAt time.Time `json:"expiresAt" gorm:"index;comment:过期时间"`
RefreshExpiresAt *time.Time `json:"refreshExpiresAt" gorm:"comment:刷新Token过期时间"`
IPAddress string `json:"ipAddress" gorm:"type:varchar(100);comment:IP地址"`
UserAgent string `json:"userAgent" gorm:"type:text;comment:用户代理"`
DeviceInfo datatypes.JSON `json:"deviceInfo" gorm:"type:jsonb;comment:设备信息"`
}
func (AppUserSession) TableName() string {
return "app_user_sessions"
}

View File

@@ -0,0 +1,56 @@
package app
import (
"time"
"gorm.io/datatypes"
"gorm.io/gorm"
)
// Conversation 对话会话模型
type Conversation struct {
ID uint `gorm:"primarykey" json:"id"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
UserID uint `gorm:"index;not null" json:"userId"` // 所属用户ID
CharacterID uint `gorm:"index;not null" json:"characterId"` // 角色卡ID
Title string `gorm:"type:varchar(200)" json:"title"` // 对话标题
// 对话配置
PresetID *uint `gorm:"index" json:"presetId"` // 使用的预设ID
AIProvider string `gorm:"type:varchar(50)" json:"aiProvider"` // AI提供商 (openai/anthropic)
Model string `gorm:"type:varchar(100)" json:"model"` // 使用的模型
Settings datatypes.JSON `gorm:"type:jsonb" json:"settings"` // 对话设置 (temperature等)
// 统计信息
MessageCount int `gorm:"default:0" json:"messageCount"` // 消息数量
TokenCount int `gorm:"default:0" json:"tokenCount"` // Token使用量
}
// TableName 指定表名
func (Conversation) TableName() string {
return "conversations"
}
// Message 消息模型
type Message struct {
ID uint `gorm:"primarykey" json:"id"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
ConversationID uint `gorm:"index;not null" json:"conversationId"` // 所属对话ID
Role string `gorm:"type:varchar(20);not null" json:"role"` // 角色 (user/assistant/system)
Content string `gorm:"type:text;not null" json:"content"` // 消息内容
// 元数据
TokenCount int `gorm:"default:0" json:"tokenCount"` // Token数量
Metadata datatypes.JSON `gorm:"type:jsonb" json:"metadata"` // 额外元数据
}
// TableName 指定表名
func (Message) TableName() string {
return "messages"
}

View File

@@ -0,0 +1,44 @@
package app
import (
"gorm.io/datatypes"
"gorm.io/gorm"
)
// AIPreset AI预设配置模型
type AIPreset struct {
gorm.Model
UserID uint `json:"userId" gorm:"not null;index:idx_preset_user"`
Name string `json:"name" gorm:"not null;size:100"`
Description string `json:"description" gorm:"size:500"`
IsPublic bool `json:"isPublic" gorm:"default:false;index:idx_preset_public"`
IsDefault bool `json:"isDefault" gorm:"default:false"`
// Sampling Parameters (stored as individual fields for query efficiency)
Temperature float64 `json:"temperature" gorm:"default:1.0"`
TopP float64 `json:"topP" gorm:"default:1.0"`
TopK int `json:"topK" gorm:"default:0"`
FrequencyPenalty float64 `json:"frequencyPenalty" gorm:"default:0"`
PresencePenalty float64 `json:"presencePenalty" gorm:"default:0"`
MaxTokens int `json:"maxTokens" gorm:"default:2000"`
RepetitionPenalty float64 `json:"repetitionPenalty" gorm:"default:1.0"`
MinP float64 `json:"minP" gorm:"default:0"`
TopA float64 `json:"topA" gorm:"default:0"`
// Prompt Configuration (stored as JSON for flexibility)
SystemPrompt string `json:"systemPrompt" gorm:"type:text"`
StopSequences datatypes.JSON `json:"stopSequences" gorm:"type:jsonb"`
// SillyTavern Extensions (for full compatibility)
Extensions datatypes.JSON `json:"extensions" gorm:"type:jsonb"`
// Usage Statistics
UseCount int `json:"useCount" gorm:"default:0"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
}
// TableName 指定表名
func (AIPreset) TableName() string {
return "ai_presets"
}

View File

@@ -0,0 +1,37 @@
package request
// CreateAIConfigRequest 创建AI配置请求
type CreateAIConfigRequest struct {
Name string `json:"name" binding:"required,max=100"`
Provider string `json:"provider" binding:"required,oneof=openai anthropic custom"`
BaseURL string `json:"baseUrl" binding:"required,url"`
APIKey string `json:"apiKey" binding:"required"`
DefaultModel string `json:"defaultModel"`
Settings map[string]interface{} `json:"settings"`
}
// UpdateAIConfigRequest 更新AI配置请求
type UpdateAIConfigRequest struct {
Name string `json:"name" binding:"max=100"`
BaseURL string `json:"baseUrl" binding:"omitempty,url"`
APIKey string `json:"apiKey"`
DefaultModel string `json:"defaultModel"`
Settings map[string]interface{} `json:"settings"`
IsActive *bool `json:"isActive"`
IsDefault *bool `json:"isDefault"`
}
// TestAIConfigRequest 测试AI配置请求
type TestAIConfigRequest struct {
Provider string `json:"provider" binding:"required,oneof=openai anthropic custom"`
BaseURL string `json:"baseUrl" binding:"required,url"`
APIKey string `json:"apiKey" binding:"required"`
Model string `json:"model"`
}
// GetModelsRequest 获取模型列表请求
type GetModelsRequest struct {
Provider string `json:"provider" binding:"required,oneof=openai anthropic custom"`
BaseURL string `json:"baseUrl" binding:"required,url"`
APIKey string `json:"apiKey" binding:"required"`
}

View File

@@ -0,0 +1,37 @@
package request
// RegisterRequest 用户注册请求
type RegisterRequest struct {
Username string `json:"username" binding:"required,min=3,max=32"`
Password string `json:"password" binding:"required,min=6,max=32"`
NickName string `json:"nickName" binding:"max=50"`
Email string `json:"email" binding:"omitempty,email"`
Phone string `json:"phone" binding:"omitempty"`
}
// LoginRequest 用户登录请求
type LoginRequest struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
// RefreshTokenRequest 刷新 Token 请求
type RefreshTokenRequest struct {
RefreshToken string `json:"refreshToken" binding:"required"`
}
// ChangePasswordRequest 修改密码请求
type ChangePasswordRequest struct {
OldPassword string `json:"oldPassword" binding:"required"`
NewPassword string `json:"newPassword" binding:"required,min=6,max=32"`
}
// UpdateProfileRequest 更新用户信息请求
type UpdateProfileRequest struct {
NickName string `json:"nickName" binding:"max=50"`
Email string `json:"email" binding:"omitempty,email"`
Phone string `json:"phone"`
Avatar string `json:"avatar"`
Preferences string `json:"preferences"` // JSON 字符串
AISettings string `json:"aiSettings"` // JSON 字符串
}

View File

@@ -0,0 +1,52 @@
package request
// CreateCharacterRequest 创建角色卡请求
type CreateCharacterRequest struct {
Name string `json:"name" binding:"required,max=100"`
Avatar string `json:"avatar"`
Creator string `json:"creator" binding:"max=100"`
Version string `json:"version" binding:"max=50"`
Description string `json:"description"`
Personality string `json:"personality"`
Scenario string `json:"scenario"`
FirstMes string `json:"firstMes"`
MesExample string `json:"mesExample"`
CreatorNotes string `json:"creatorNotes"`
SystemPrompt string `json:"systemPrompt"`
PostHistoryInstructions string `json:"postHistoryInstructions"`
Tags []string `json:"tags"`
AlternateGreetings []string `json:"alternateGreetings"`
CharacterBook map[string]interface{} `json:"characterBook"`
Extensions map[string]interface{} `json:"extensions"`
IsPublic bool `json:"isPublic"`
}
// UpdateCharacterRequest 更新角色卡请求
type UpdateCharacterRequest struct {
Name string `json:"name" binding:"max=100"`
Avatar string `json:"avatar"`
Creator string `json:"creator" binding:"max=100"`
Version string `json:"version" binding:"max=50"`
Description string `json:"description"`
Personality string `json:"personality"`
Scenario string `json:"scenario"`
FirstMes string `json:"firstMes"`
MesExample string `json:"mesExample"`
CreatorNotes string `json:"creatorNotes"`
SystemPrompt string `json:"systemPrompt"`
PostHistoryInstructions string `json:"postHistoryInstructions"`
Tags []string `json:"tags"`
AlternateGreetings []string `json:"alternateGreetings"`
CharacterBook map[string]interface{} `json:"characterBook"`
Extensions map[string]interface{} `json:"extensions"`
IsPublic bool `json:"isPublic"`
}
// GetCharacterListRequest 获取角色卡列表请求
type GetCharacterListRequest struct {
Page int `form:"page" binding:"min=1"`
PageSize int `form:"pageSize" binding:"min=1,max=100"`
Keyword string `form:"keyword"`
Tag string `form:"tag"`
IsPublic *bool `form:"isPublic"`
}

View File

@@ -0,0 +1,32 @@
package request
// CreateConversationRequest 创建对话请求
type CreateConversationRequest struct {
CharacterID uint `json:"characterId" binding:"required"`
Title string `json:"title" binding:"max=200"`
PresetID *uint `json:"presetId"`
AIProvider string `json:"aiProvider" binding:"omitempty,oneof=openai anthropic"`
Model string `json:"model"`
}
// SendMessageRequest 发送消息请求
type SendMessageRequest struct {
Content string `json:"content" binding:"required"`
}
// GetConversationListRequest 获取对话列表请求
type GetConversationListRequest struct {
Page int `form:"page" binding:"min=1"`
PageSize int `form:"pageSize" binding:"min=1,max=100"`
}
// GetMessageListRequest 获取消息列表请求
type GetMessageListRequest struct {
Page int `form:"page" binding:"min=1"`
PageSize int `form:"pageSize" binding:"min=1,max=100"`
}
// UpdateConversationSettingsRequest 更新对话设置请求
type UpdateConversationSettingsRequest struct {
Settings map[string]interface{} `json:"settings" binding:"required"`
}

View File

@@ -0,0 +1,47 @@
package request
// CreatePresetRequest 创建预设请求
type CreatePresetRequest struct {
Name string `json:"name" binding:"required,min=1,max=100"`
Description string `json:"description" binding:"max=500"`
IsPublic bool `json:"isPublic"`
Temperature float64 `json:"temperature" binding:"min=0,max=2"`
TopP float64 `json:"topP" binding:"min=0,max=1"`
TopK int `json:"topK" binding:"min=0"`
FrequencyPenalty float64 `json:"frequencyPenalty" binding:"min=-2,max=2"`
PresencePenalty float64 `json:"presencePenalty" binding:"min=-2,max=2"`
MaxTokens int `json:"maxTokens" binding:"min=1,max=32000"`
RepetitionPenalty float64 `json:"repetitionPenalty"`
MinP float64 `json:"minP"`
TopA float64 `json:"topA"`
SystemPrompt string `json:"systemPrompt"`
StopSequences []string `json:"stopSequences"`
Extensions map[string]interface{} `json:"extensions"`
}
// UpdatePresetRequest 更新预设请求
type UpdatePresetRequest struct {
Name string `json:"name" binding:"min=1,max=100"`
Description string `json:"description" binding:"max=500"`
IsPublic *bool `json:"isPublic"`
Temperature *float64 `json:"temperature" binding:"omitempty,min=0,max=2"`
TopP *float64 `json:"topP" binding:"omitempty,min=0,max=1"`
TopK *int `json:"topK" binding:"omitempty,min=0"`
FrequencyPenalty *float64 `json:"frequencyPenalty" binding:"omitempty,min=-2,max=2"`
PresencePenalty *float64 `json:"presencePenalty" binding:"omitempty,min=-2,max=2"`
MaxTokens *int `json:"maxTokens" binding:"omitempty,min=1,max=32000"`
RepetitionPenalty *float64 `json:"repetitionPenalty"`
MinP *float64 `json:"minP"`
TopA *float64 `json:"topA"`
SystemPrompt *string `json:"systemPrompt"`
StopSequences []string `json:"stopSequences"`
Extensions map[string]interface{} `json:"extensions"`
}
// GetPresetListRequest 获取预设列表请求
type GetPresetListRequest struct {
Page int `form:"page" binding:"min=1"`
PageSize int `form:"pageSize" binding:"min=1,max=100"`
Keyword string `form:"keyword"`
IsPublic *bool `form:"isPublic"`
}

View File

@@ -0,0 +1,88 @@
package response
import (
"encoding/json"
"time"
"git.echol.cn/loser/st/server/model/app"
)
// AIConfigResponse AI配置响应
type AIConfigResponse struct {
ID uint `json:"id"`
Name string `json:"name"`
Provider string `json:"provider"`
BaseURL string `json:"baseUrl"`
APIKey string `json:"apiKey"` // 前端显示时应该脱敏
Models []string `json:"models"`
DefaultModel string `json:"defaultModel"`
Settings map[string]interface{} `json:"settings"`
IsActive bool `json:"isActive"`
IsDefault bool `json:"isDefault"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
// AIConfigListResponse AI配置列表响应
type AIConfigListResponse struct {
List []AIConfigResponse `json:"list"`
Total int64 `json:"total"`
}
// TestAIConfigResponse 测试AI配置响应
type TestAIConfigResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
Latency int64 `json:"latency"` // 响应延迟(ms)
}
// GetModelsResponse 获取模型列表响应
type GetModelsResponse struct {
Models []ModelInfo `json:"models"`
}
// ModelInfo 模型信息
type ModelInfo struct {
ID string `json:"id"`
Name string `json:"name"`
OwnedBy string `json:"ownedBy"`
}
// ToAIConfigResponse 转换为AI配置响应结构
func ToAIConfigResponse(config *app.AIConfig) AIConfigResponse {
resp := AIConfigResponse{
ID: config.ID,
Name: config.Name,
Provider: config.Provider,
BaseURL: config.BaseURL,
APIKey: maskAPIKey(config.APIKey),
DefaultModel: config.DefaultModel,
IsActive: config.IsActive,
IsDefault: config.IsDefault,
CreatedAt: config.CreatedAt,
UpdatedAt: config.UpdatedAt,
}
// 解析 JSON 字段
if len(config.Models) > 0 {
var models []string
json.Unmarshal(config.Models, &models)
resp.Models = models
}
if len(config.Settings) > 0 {
var settings map[string]interface{}
json.Unmarshal(config.Settings, &settings)
resp.Settings = settings
}
return resp
}
// maskAPIKey 脱敏API Key
func maskAPIKey(apiKey string) string {
if len(apiKey) <= 8 {
return "****"
}
return apiKey[:4] + "****" + apiKey[len(apiKey)-4:]
}

View File

@@ -0,0 +1,55 @@
package response
import (
"time"
"git.echol.cn/loser/st/server/model/app"
)
// AppUserResponse 用户信息响应
type AppUserResponse struct {
ID uint `json:"id"`
UUID string `json:"uuid"`
Username string `json:"username"`
NickName string `json:"nickName"`
Email string `json:"email"`
Phone string `json:"phone"`
Avatar string `json:"avatar"`
Status string `json:"status"`
Enable bool `json:"enable"`
IsAdmin bool `json:"isAdmin"`
LastLoginAt *time.Time `json:"lastLoginAt"`
LastLoginIP string `json:"lastLoginIp"`
ChatCount int `json:"chatCount"`
MessageCount int `json:"messageCount"`
CreatedAt time.Time `json:"createdAt"`
}
// LoginResponse 登录响应
type LoginResponse struct {
User AppUserResponse `json:"user"`
Token string `json:"token"`
RefreshToken string `json:"refreshToken"`
ExpiresAt int64 `json:"expiresAt"`
}
// ToAppUserResponse 转换为用户响应结构
func ToAppUserResponse(user *app.AppUser) AppUserResponse {
return AppUserResponse{
ID: user.ID,
UUID: user.UUID,
Username: user.Username,
NickName: user.NickName,
Email: user.Email,
Phone: user.Phone,
Avatar: user.Avatar,
Status: user.Status,
Enable: user.Enable,
IsAdmin: user.IsAdmin,
LastLoginAt: user.LastLoginAt,
LastLoginIP: user.LastLoginIP,
ChatCount: user.ChatCount,
MessageCount: user.MessageCount,
CreatedAt: user.CreatedAt,
}
}

View File

@@ -0,0 +1,108 @@
package response
import (
"encoding/json"
"time"
"git.echol.cn/loser/st/server/model/app"
)
// CharacterResponse 角色卡响应
type CharacterResponse struct {
ID uint `json:"id"`
Name string `json:"name"`
Avatar string `json:"avatar"`
Creator string `json:"creator"`
Version string `json:"version"`
Description string `json:"description"`
Personality string `json:"personality"`
Scenario string `json:"scenario"`
FirstMes string `json:"firstMes"`
MesExample string `json:"mesExample"`
CreatorNotes string `json:"creatorNotes"`
SystemPrompt string `json:"systemPrompt"`
PostHistoryInstructions string `json:"postHistoryInstructions"`
Tags []string `json:"tags"`
AlternateGreetings []string `json:"alternateGreetings"`
CharacterBook map[string]interface{} `json:"characterBook"`
Extensions map[string]interface{} `json:"extensions"`
Spec string `json:"spec"`
SpecVersion string `json:"specVersion"`
IsPublic bool `json:"isPublic"`
UseCount int `json:"useCount"`
FavoriteCount int `json:"favoriteCount"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
// CharacterSimpleResponse 角色卡简化响应(用于列表)
type CharacterSimpleResponse struct {
ID uint `json:"id"`
Name string `json:"name"`
Avatar string `json:"avatar"`
Description string `json:"description"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
// CharacterListResponse 角色卡列表响应
type CharacterListResponse struct {
List []CharacterResponse `json:"list"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
}
// ToCharacterResponse 转换为角色卡响应结构
func ToCharacterResponse(character *app.AICharacter) CharacterResponse {
resp := CharacterResponse{
ID: character.ID,
Name: character.Name,
Avatar: character.Avatar,
Creator: character.Creator,
Version: character.Version,
Description: character.Description,
Personality: character.Personality,
Scenario: character.Scenario,
FirstMes: character.FirstMes,
MesExample: character.MesExample,
CreatorNotes: character.CreatorNotes,
SystemPrompt: character.SystemPrompt,
PostHistoryInstructions: character.PostHistoryInstructions,
Spec: character.Spec,
SpecVersion: character.SpecVersion,
IsPublic: character.IsPublic,
UseCount: character.UseCount,
FavoriteCount: character.FavoriteCount,
CreatedAt: character.CreatedAt,
UpdatedAt: character.UpdatedAt,
}
// 解析 JSON 字段
if len(character.Tags) > 0 {
json.Unmarshal(character.Tags, &resp.Tags)
}
if len(character.AlternateGreetings) > 0 {
json.Unmarshal(character.AlternateGreetings, &resp.AlternateGreetings)
}
if len(character.CharacterBook) > 0 {
json.Unmarshal(character.CharacterBook, &resp.CharacterBook)
}
if len(character.Extensions) > 0 {
json.Unmarshal(character.Extensions, &resp.Extensions)
}
return resp
}
// ToCharacterSimpleResponse 转换为角色卡简化响应结构(用于列表)
func ToCharacterSimpleResponse(character *app.AICharacter) CharacterSimpleResponse {
return CharacterSimpleResponse{
ID: character.ID,
Name: character.Name,
Avatar: character.Avatar,
Description: character.Description,
CreatedAt: character.CreatedAt,
UpdatedAt: character.UpdatedAt,
}
}

View File

@@ -0,0 +1,122 @@
package response
import (
"encoding/json"
"time"
"git.echol.cn/loser/st/server/model/app"
)
// ConversationResponse 对话响应
type ConversationResponse struct {
ID uint `json:"id"`
CharacterID uint `json:"characterId"`
Title string `json:"title"`
PresetID *uint `json:"presetId"`
AIProvider string `json:"aiProvider"`
Model string `json:"model"`
Settings map[string]interface{} `json:"settings,omitempty"`
MessageCount int `json:"messageCount"`
TokenCount int `json:"tokenCount"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
// 关联数据
Character *CharacterResponse `json:"character,omitempty"`
}
// ConversationListItemResponse 对话列表项响应(轻量级)
type ConversationListItemResponse struct {
ID uint `json:"id"`
CharacterID uint `json:"characterId"`
Title string `json:"title"`
MessageCount int `json:"messageCount"`
TokenCount int `json:"tokenCount"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
Character *CharacterSimpleResponse `json:"character,omitempty"`
}
// MessageResponse 消息响应
type MessageResponse struct {
ID uint `json:"id"`
ConversationID uint `json:"conversationId"`
Role string `json:"role"`
Content string `json:"content"`
TokenCount int `json:"tokenCount"`
CreatedAt time.Time `json:"createdAt"`
}
// ConversationListResponse 对话列表响应
type ConversationListResponse struct {
List []ConversationListItemResponse `json:"list"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
}
// MessageListResponse 消息列表响应
type MessageListResponse struct {
List []MessageResponse `json:"list"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
}
// ToConversationResponse 转换为对话响应结构
func ToConversationResponse(conv *app.Conversation) ConversationResponse {
// 解析 settings JSON
var settings map[string]interface{}
if len(conv.Settings) > 0 {
// 尝试解析 JSON,如果失败则返回 nil
if err := json.Unmarshal(conv.Settings, &settings); err != nil {
settings = nil
}
}
return ConversationResponse{
ID: conv.ID,
CharacterID: conv.CharacterID,
Title: conv.Title,
PresetID: conv.PresetID,
AIProvider: conv.AIProvider,
Model: conv.Model,
Settings: settings,
MessageCount: conv.MessageCount,
TokenCount: conv.TokenCount,
CreatedAt: conv.CreatedAt,
UpdatedAt: conv.UpdatedAt,
}
}
// ToMessageResponse 转换为消息响应结构
func ToMessageResponse(msg *app.Message) MessageResponse {
return MessageResponse{
ID: msg.ID,
ConversationID: msg.ConversationID,
Role: msg.Role,
Content: msg.Content,
TokenCount: msg.TokenCount,
CreatedAt: msg.CreatedAt,
}
}
// ToConversationListItemResponse 转换为对话列表项响应结构(轻量级)
func ToConversationListItemResponse(conv *app.Conversation, character *app.AICharacter) ConversationListItemResponse {
resp := ConversationListItemResponse{
ID: conv.ID,
CharacterID: conv.CharacterID,
Title: conv.Title,
MessageCount: conv.MessageCount,
TokenCount: conv.TokenCount,
CreatedAt: conv.CreatedAt,
UpdatedAt: conv.UpdatedAt,
}
if character != nil {
simpleChar := ToCharacterSimpleResponse(character)
resp.Character = &simpleChar
}
return resp
}

View File

@@ -0,0 +1,78 @@
package response
import (
"encoding/json"
"time"
"git.echol.cn/loser/st/server/model/app"
)
// PresetResponse 预设响应
type PresetResponse struct {
ID uint `json:"id"`
UserID uint `json:"userId"`
Name string `json:"name"`
Description string `json:"description"`
IsPublic bool `json:"isPublic"`
IsDefault bool `json:"isDefault"`
Temperature float64 `json:"temperature"`
TopP float64 `json:"topP"`
TopK int `json:"topK"`
FrequencyPenalty float64 `json:"frequencyPenalty"`
PresencePenalty float64 `json:"presencePenalty"`
MaxTokens int `json:"maxTokens"`
RepetitionPenalty float64 `json:"repetitionPenalty"`
MinP float64 `json:"minP"`
TopA float64 `json:"topA"`
SystemPrompt string `json:"systemPrompt"`
StopSequences []string `json:"stopSequences"`
Extensions map[string]interface{} `json:"extensions"`
UseCount int `json:"useCount"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
// PresetListResponse 预设列表响应
type PresetListResponse struct {
List []PresetResponse `json:"list"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
}
// ToPresetResponse 转换为预设响应结构
func ToPresetResponse(preset *app.AIPreset) PresetResponse {
var stopSequences []string
if len(preset.StopSequences) > 0 {
json.Unmarshal(preset.StopSequences, &stopSequences)
}
var extensions map[string]interface{}
if len(preset.Extensions) > 0 {
json.Unmarshal(preset.Extensions, &extensions)
}
return PresetResponse{
ID: preset.ID,
UserID: preset.UserID,
Name: preset.Name,
Description: preset.Description,
IsPublic: preset.IsPublic,
IsDefault: preset.IsDefault,
Temperature: preset.Temperature,
TopP: preset.TopP,
TopK: preset.TopK,
FrequencyPenalty: preset.FrequencyPenalty,
PresencePenalty: preset.PresencePenalty,
MaxTokens: preset.MaxTokens,
RepetitionPenalty: preset.RepetitionPenalty,
MinP: preset.MinP,
TopA: preset.TopA,
SystemPrompt: preset.SystemPrompt,
StopSequences: stopSequences,
Extensions: extensions,
UseCount: preset.UseCount,
CreatedAt: preset.CreatedAt,
UpdatedAt: preset.UpdatedAt,
}
}

View File

@@ -0,0 +1,43 @@
package common
import (
"database/sql/driver"
"encoding/json"
"errors"
)
type JSONMap map[string]interface{}
func (m JSONMap) Value() (driver.Value, error) {
if m == nil {
return nil, nil
}
return json.Marshal(m)
}
func (m *JSONMap) Scan(value interface{}) error {
if value == nil {
*m = make(map[string]interface{})
return nil
}
var err error
switch value.(type) {
case []byte:
err = json.Unmarshal(value.([]byte), m)
case string:
err = json.Unmarshal([]byte(value.(string)), m)
default:
err = errors.New("basetypes.JSONMap.Scan: invalid value type")
}
if err != nil {
return err
}
return nil
}
type TreeNode[T any] interface {
GetChildren() []T
SetChildren(children T)
GetID() int
GetParentID() int
}

View File

@@ -0,0 +1,7 @@
package common
type ClearDB struct {
TableName string
CompareField string
Interval string
}

View File

@@ -0,0 +1,21 @@
package common
import (
"github.com/gin-gonic/gin"
)
// GetAppUserID 从上下文获取前台用户 ID
func GetAppUserID(c *gin.Context) uint {
if userID, exists := c.Get("appUserId"); exists {
return userID.(uint)
}
return 0
}
// GetAppUsername 从上下文获取前台用户名
func GetAppUsername(c *gin.Context) string {
if username, exists := c.Get("appUsername"); exists {
return username.(string)
}
return ""
}

View File

@@ -0,0 +1,48 @@
package request
import (
"gorm.io/gorm"
)
// PageInfo Paging common input parameter structure
type PageInfo struct {
Page int `json:"page" form:"page,default=1"` // 页码
PageSize int `json:"pageSize" form:"pageSize,default=20"` // 每页大小
Keyword string `json:"keyword" form:"keyword"` // 关键字
}
func (r *PageInfo) Paginate() func(db *gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
if r.Page <= 0 {
r.Page = 1
}
switch {
case r.PageSize > 100:
r.PageSize = 100
case r.PageSize <= 0:
r.PageSize = 10
}
offset := (r.Page - 1) * r.PageSize
return db.Offset(offset).Limit(r.PageSize)
}
}
// GetById Find by id structure
type GetById struct {
ID int `json:"id" form:"id"` // 主键ID
}
func (r *GetById) Uint() uint {
return uint(r.ID)
}
type IdsReq struct {
Ids []int `json:"ids" form:"ids"`
}
// GetAuthorityId Get role by id structure
type GetAuthorityId struct {
AuthorityId uint `json:"authorityId" form:"authorityId"` // 角色ID
}
type Empty struct{}

View File

@@ -0,0 +1,8 @@
package response
type PageResult struct {
List interface{} `json:"list"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
}

View File

@@ -0,0 +1,62 @@
package response
import (
"net/http"
"github.com/gin-gonic/gin"
)
type Response struct {
Code int `json:"code"`
Data interface{} `json:"data"`
Msg string `json:"msg"`
}
const (
ERROR = 7
SUCCESS = 0
)
func Result(code int, data interface{}, msg string, c *gin.Context) {
c.JSON(http.StatusOK, Response{
code,
data,
msg,
})
}
func Ok(c *gin.Context) {
Result(SUCCESS, map[string]interface{}{}, "操作成功", c)
}
func OkWithMessage(message string, c *gin.Context) {
Result(SUCCESS, map[string]interface{}{}, message, c)
}
func OkWithData(data interface{}, c *gin.Context) {
Result(SUCCESS, data, "成功", c)
}
func OkWithDetailed(data interface{}, message string, c *gin.Context) {
Result(SUCCESS, data, message, c)
}
func Fail(c *gin.Context) {
Result(ERROR, map[string]interface{}{}, "操作失败", c)
}
func FailWithMessage(message string, c *gin.Context) {
Result(ERROR, map[string]interface{}{}, message, c)
}
func NoAuth(message string, c *gin.Context) {
c.JSON(http.StatusUnauthorized, Response{
7,
nil,
message,
})
}
func FailWithDetailed(data interface{}, message string, c *gin.Context) {
Result(ERROR, data, message, c)
}

View File

@@ -0,0 +1,16 @@
package example
import (
"git.echol.cn/loser/st/server/global"
)
type ExaAttachmentCategory struct {
global.GVA_MODEL
Name string `json:"name" form:"name" gorm:"default:null;type:varchar(255);column:name;comment:分类名称;"`
Pid uint `json:"pid" form:"pid" gorm:"default:0;type:int;column:pid;comment:父节点ID;"`
Children []*ExaAttachmentCategory `json:"children" gorm:"-"`
}
func (ExaAttachmentCategory) TableName() string {
return "exa_attachment_category"
}

View File

@@ -0,0 +1,24 @@
package example
import (
"git.echol.cn/loser/st/server/global"
)
// file struct, 文件结构体
type ExaFile struct {
global.GVA_MODEL
FileName string
FileMd5 string
FilePath string
ExaFileChunk []ExaFileChunk
ChunkTotal int
IsFinish bool
}
// file chunk struct, 切片结构体
type ExaFileChunk struct {
global.GVA_MODEL
ExaFileID uint
FileChunkNumber int
FileChunkPath string
}

View File

@@ -0,0 +1,15 @@
package example
import (
"git.echol.cn/loser/st/server/global"
"git.echol.cn/loser/st/server/model/system"
)
type ExaCustomer struct {
global.GVA_MODEL
CustomerName string `json:"customerName" form:"customerName" gorm:"comment:客户名"` // 客户名
CustomerPhoneData string `json:"customerPhoneData" form:"customerPhoneData" gorm:"comment:客户手机号"` // 客户手机号
SysUserID uint `json:"sysUserId" form:"sysUserId" gorm:"comment:管理ID"` // 管理ID
SysUserAuthorityID uint `json:"sysUserAuthorityID" form:"sysUserAuthorityID" gorm:"comment:管理角色ID"` // 管理角色ID
SysUser system.SysUser `json:"sysUser" form:"sysUser" gorm:"comment:管理详情"` // 管理详情
}

View File

@@ -0,0 +1,18 @@
package example
import (
"git.echol.cn/loser/st/server/global"
)
type ExaFileUploadAndDownload struct {
global.GVA_MODEL
Name string `json:"name" form:"name" gorm:"column:name;comment:文件名"` // 文件名
ClassId int `json:"classId" form:"classId" gorm:"default:0;type:int;column:class_id;comment:分类id;"` // 分类id
Url string `json:"url" form:"url" gorm:"column:url;comment:文件地址"` // 文件地址
Tag string `json:"tag" form:"tag" gorm:"column:tag;comment:文件标签"` // 文件标签
Key string `json:"key" form:"key" gorm:"column:key;comment:编号"` // 编号
}
func (ExaFileUploadAndDownload) TableName() string {
return "exa_file_upload_and_downloads"
}

View File

@@ -0,0 +1,10 @@
package request
import (
"git.echol.cn/loser/st/server/model/common/request"
)
type ExaAttachmentCategorySearch struct {
ClassId int `json:"classId" form:"classId"`
request.PageInfo
}

View File

@@ -0,0 +1,11 @@
package response
import "git.echol.cn/loser/st/server/model/example"
type FilePathResponse struct {
FilePath string `json:"filePath"`
}
type FileResponse struct {
File example.ExaFile `json:"file"`
}

View File

@@ -0,0 +1,7 @@
package response
import "git.echol.cn/loser/st/server/model/example"
type ExaCustomerResponse struct {
Customer example.ExaCustomer `json:"customer"`
}

View File

@@ -0,0 +1,7 @@
package response
import "git.echol.cn/loser/st/server/model/example"
type ExaFileResponse struct {
File example.ExaFileUploadAndDownload `json:"file"`
}

View File

@@ -0,0 +1,21 @@
package request
import (
jwt "github.com/golang-jwt/jwt/v5"
"github.com/google/uuid"
)
// CustomClaims structure
type CustomClaims struct {
BaseClaims
BufferTime int64
jwt.RegisteredClaims
}
type BaseClaims struct {
UUID uuid.UUID
ID uint
Username string
NickName string
AuthorityId uint
}

View File

@@ -0,0 +1,14 @@
package request
import (
"git.echol.cn/loser/st/server/model/common/request"
"git.echol.cn/loser/st/server/model/system"
)
// api分页条件查询及排序结构体
type SearchApiParams struct {
system.SysApi
request.PageInfo
OrderKey string `json:"orderKey"` // 排序
Desc bool `json:"desc"` // 排序方式:升序false(默认)|降序true
}

View File

@@ -0,0 +1,12 @@
package request
import (
"git.echol.cn/loser/st/server/model/common/request"
"git.echol.cn/loser/st/server/model/system"
)
type SysApiTokenSearch struct {
system.SysApiToken
request.PageInfo
Status *bool `json:"status" form:"status"`
}

View File

@@ -0,0 +1,7 @@
package request
type SysAuthorityBtnReq struct {
MenuID uint `json:"menuID"`
AuthorityId uint `json:"authorityId"`
Selected []uint `json:"selected"`
}

View File

@@ -0,0 +1,292 @@
package request
import (
"encoding/json"
"fmt"
"go/token"
"strings"
"git.echol.cn/loser/st/server/global"
model "git.echol.cn/loser/st/server/model/system"
"github.com/pkg/errors"
)
type AutoCode struct {
Package string `json:"package"`
PackageT string `json:"-"`
TableName string `json:"tableName" example:"表名"` // 表名
BusinessDB string `json:"businessDB" example:"业务数据库"` // 业务数据库
StructName string `json:"structName" example:"Struct名称"` // Struct名称
PackageName string `json:"packageName" example:"文件名称"` // 文件名称
Description string `json:"description" example:"Struct中文名称"` // Struct中文名称
Abbreviation string `json:"abbreviation" example:"Struct简称"` // Struct简称
HumpPackageName string `json:"humpPackageName" example:"go文件名称"` // go文件名称
GvaModel bool `json:"gvaModel" example:"false"` // 是否使用gva默认Model
AutoMigrate bool `json:"autoMigrate" example:"false"` // 是否自动迁移表结构
AutoCreateResource bool `json:"autoCreateResource" example:"false"` // 是否自动创建资源标识
AutoCreateApiToSql bool `json:"autoCreateApiToSql" example:"false"` // 是否自动创建api
AutoCreateMenuToSql bool `json:"autoCreateMenuToSql" example:"false"` // 是否自动创建menu
AutoCreateBtnAuth bool `json:"autoCreateBtnAuth" example:"false"` // 是否自动创建按钮权限
OnlyTemplate bool `json:"onlyTemplate" example:"false"` // 是否只生成模板
IsTree bool `json:"isTree" example:"false"` // 是否树形结构
TreeJson string `json:"treeJson" example:"展示的树json字段"` // 展示的树json字段
IsAdd bool `json:"isAdd" example:"false"` // 是否新增
Fields []*AutoCodeField `json:"fields"`
GenerateWeb bool `json:"generateWeb" example:"true"` // 是否生成web
GenerateServer bool `json:"generateServer" example:"true"` // 是否生成server
Module string `json:"-"`
DictTypes []string `json:"-"`
PrimaryField *AutoCodeField `json:"primaryField"`
DataSourceMap map[string]*DataSource `json:"-"`
HasPic bool `json:"-"`
HasFile bool `json:"-"`
HasTimer bool `json:"-"`
NeedSort bool `json:"-"`
NeedJSON bool `json:"-"`
HasRichText bool `json:"-"`
HasDataSource bool `json:"-"`
HasSearchTimer bool `json:"-"`
HasArray bool `json:"-"`
HasExcel bool `json:"-"`
}
type DataSource struct {
DBName string `json:"dbName"`
Table string `json:"table"`
Label string `json:"label"`
Value string `json:"value"`
Association int `json:"association"` // 关联关系 1 一对一 2 一对多
HasDeletedAt bool `json:"hasDeletedAt"`
}
func (r *AutoCode) Apis() []model.SysApi {
return []model.SysApi{
{
Path: "/" + r.Abbreviation + "/" + "create" + r.StructName,
Description: "新增" + r.Description,
ApiGroup: r.Description,
Method: "POST",
},
{
Path: "/" + r.Abbreviation + "/" + "delete" + r.StructName,
Description: "删除" + r.Description,
ApiGroup: r.Description,
Method: "DELETE",
},
{
Path: "/" + r.Abbreviation + "/" + "delete" + r.StructName + "ByIds",
Description: "批量删除" + r.Description,
ApiGroup: r.Description,
Method: "DELETE",
},
{
Path: "/" + r.Abbreviation + "/" + "update" + r.StructName,
Description: "更新" + r.Description,
ApiGroup: r.Description,
Method: "PUT",
},
{
Path: "/" + r.Abbreviation + "/" + "find" + r.StructName,
Description: "根据ID获取" + r.Description,
ApiGroup: r.Description,
Method: "GET",
},
{
Path: "/" + r.Abbreviation + "/" + "get" + r.StructName + "List",
Description: "获取" + r.Description + "列表",
ApiGroup: r.Description,
Method: "GET",
},
}
}
func (r *AutoCode) Menu(template string) model.SysBaseMenu {
component := fmt.Sprintf("view/%s/%s/%s.vue", r.Package, r.PackageName, r.PackageName)
if template != "package" {
component = fmt.Sprintf("plugin/%s/view/%s.vue", r.Package, r.PackageName)
}
return model.SysBaseMenu{
ParentId: 0,
Path: r.Abbreviation,
Name: r.Abbreviation,
Component: component,
Meta: model.Meta{
Title: r.Description,
},
}
}
// Pretreatment 预处理
// Author [SliverHorn](https://github.com/SliverHorn)
func (r *AutoCode) Pretreatment() error {
r.Module = global.GVA_CONFIG.AutoCode.Module
if token.IsKeyword(r.Abbreviation) {
r.Abbreviation = r.Abbreviation + "_"
} // go 关键字处理
if strings.HasSuffix(r.HumpPackageName, "test") {
r.HumpPackageName = r.HumpPackageName + "_"
} // test
length := len(r.Fields)
dict := make(map[string]string, length)
r.DataSourceMap = make(map[string]*DataSource, length)
for i := 0; i < length; i++ {
if r.Fields[i].Excel {
r.HasExcel = true
}
if r.Fields[i].DictType != "" {
dict[r.Fields[i].DictType] = ""
}
if r.Fields[i].Sort {
r.NeedSort = true
}
switch r.Fields[i].FieldType {
case "file":
r.HasFile = true
r.NeedJSON = true
case "json":
r.NeedJSON = true
case "array":
r.NeedJSON = true
r.HasArray = true
case "video":
r.HasPic = true
case "richtext":
r.HasRichText = true
case "picture":
r.HasPic = true
case "pictures":
r.HasPic = true
r.NeedJSON = true
case "time.Time":
r.HasTimer = true
if r.Fields[i].FieldSearchType != "" && r.Fields[i].FieldSearchType != "BETWEEN" && r.Fields[i].FieldSearchType != "NOT BETWEEN" {
r.HasSearchTimer = true
}
}
if r.Fields[i].DataSource != nil {
if r.Fields[i].DataSource.Table != "" && r.Fields[i].DataSource.Label != "" && r.Fields[i].DataSource.Value != "" {
r.HasDataSource = true
r.Fields[i].CheckDataSource = true
r.DataSourceMap[r.Fields[i].FieldJson] = r.Fields[i].DataSource
}
}
if !r.GvaModel && r.PrimaryField == nil && r.Fields[i].PrimaryKey {
r.PrimaryField = r.Fields[i]
} // 自定义主键
}
{
for key := range dict {
r.DictTypes = append(r.DictTypes, key)
}
} // DictTypes => 字典
{
if r.GvaModel {
r.PrimaryField = &AutoCodeField{
FieldName: "ID",
FieldType: "uint",
FieldDesc: "ID",
FieldJson: "ID",
DataTypeLong: "20",
Comment: "主键ID",
ColumnName: "id",
}
}
} // GvaModel
{
if r.IsAdd && r.PrimaryField == nil {
r.PrimaryField = new(AutoCodeField)
}
} // 新增字段模式下不关注主键
if r.Package == "" {
return errors.New("Package为空!")
} // 增加判断Package不为空
packages := []rune(r.Package)
if len(packages) > 0 {
if packages[0] >= 97 && packages[0] <= 122 {
packages[0] = packages[0] - 32
}
r.PackageT = string(packages)
} // PackageT 是 Package 的首字母大写
return nil
}
func (r *AutoCode) History() SysAutoHistoryCreate {
bytes, _ := json.Marshal(r)
return SysAutoHistoryCreate{
Table: r.TableName,
Package: r.Package,
Request: string(bytes),
StructName: r.StructName,
BusinessDB: r.BusinessDB,
Description: r.Description,
}
}
type AutoCodeField struct {
FieldName string `json:"fieldName"` // Field名
FieldDesc string `json:"fieldDesc"` // 中文名
FieldType string `json:"fieldType"` // Field数据类型
FieldJson string `json:"fieldJson"` // FieldJson
DataTypeLong string `json:"dataTypeLong"` // 数据库字段长度
Comment string `json:"comment"` // 数据库字段描述
ColumnName string `json:"columnName"` // 数据库字段
FieldSearchType string `json:"fieldSearchType"` // 搜索条件
FieldSearchHide bool `json:"fieldSearchHide"` // 是否隐藏查询条件
DictType string `json:"dictType"` // 字典
//Front bool `json:"front"` // 是否前端可见
Form bool `json:"form"` // 是否前端新建/编辑
Table bool `json:"table"` // 是否前端表格列
Desc bool `json:"desc"` // 是否前端详情
Excel bool `json:"excel"` // 是否导入/导出
Require bool `json:"require"` // 是否必填
DefaultValue string `json:"defaultValue"` // 是否必填
ErrorText string `json:"errorText"` // 校验失败文字
Clearable bool `json:"clearable"` // 是否可清空
Sort bool `json:"sort"` // 是否增加排序
PrimaryKey bool `json:"primaryKey"` // 是否主键
DataSource *DataSource `json:"dataSource"` // 数据源
CheckDataSource bool `json:"checkDataSource"` // 是否检查数据源
FieldIndexType string `json:"fieldIndexType"` // 索引类型
}
type AutoFunc struct {
Package string `json:"package"`
FuncName string `json:"funcName"` // 方法名称
Router string `json:"router"` // 路由名称
FuncDesc string `json:"funcDesc"` // 方法介绍
BusinessDB string `json:"businessDB"` // 业务库
StructName string `json:"structName"` // Struct名称
PackageName string `json:"packageName"` // 文件名称
Description string `json:"description"` // Struct中文名称
Abbreviation string `json:"abbreviation"` // Struct简称
HumpPackageName string `json:"humpPackageName"` // go文件名称
Method string `json:"method"` // 方法
IsPlugin bool `json:"isPlugin"` // 是否插件
IsAuth bool `json:"isAuth"` // 是否鉴权
IsPreview bool `json:"isPreview"` // 是否预览
IsAi bool `json:"isAi"` // 是否AI
ApiFunc string `json:"apiFunc"` // API方法
ServerFunc string `json:"serverFunc"` // 服务方法
JsFunc string `json:"jsFunc"` // JS方法
}
type InitMenu struct {
PlugName string `json:"plugName"`
ParentMenu string `json:"parentMenu"`
Menus []uint `json:"menus"`
}
type InitApi struct {
PlugName string `json:"plugName"`
APIs []uint `json:"apis"`
}
type InitDictionary struct {
PlugName string `json:"plugName"`
Dictionaries []uint `json:"dictionaries"`
}
type LLMAutoCode struct {
Prompt string `json:"prompt" form:"prompt" gorm:"column:prompt;comment:提示语;type:text;"` //提示语
Mode string `json:"mode" form:"mode" gorm:"column:mode;comment:模式;type:text;"` //模式
}

View File

@@ -0,0 +1,16 @@
package request
type AutoMcpTool struct {
Name string `json:"name" form:"name" binding:"required"`
Description string `json:"description" form:"description" binding:"required"`
Params []struct {
Name string `json:"name" form:"name" binding:"required"`
Description string `json:"description" form:"description" binding:"required"`
Type string `json:"type" form:"type" binding:"required"` // string, number, boolean, object, array
Required bool `json:"required" form:"required"`
Default string `json:"default" form:"default"`
} `json:"params" form:"params"`
Response []struct {
Type string `json:"type" form:"type" binding:"required"` // text, image
} `json:"response" form:"response"`
}

View File

@@ -0,0 +1,31 @@
package request
import (
"git.echol.cn/loser/st/server/global"
model "git.echol.cn/loser/st/server/model/system"
)
type SysAutoCodePackageCreate struct {
Desc string `json:"desc" example:"描述"`
Label string `json:"label" example:"展示名"`
Template string `json:"template" example:"模版"`
PackageName string `json:"packageName" example:"包名"`
Module string `json:"-" example:"模块"`
}
func (r *SysAutoCodePackageCreate) AutoCode() AutoCode {
return AutoCode{
Package: r.PackageName,
Module: global.GVA_CONFIG.AutoCode.Module,
}
}
func (r *SysAutoCodePackageCreate) Create() model.SysAutoCodePackage {
return model.SysAutoCodePackage{
Desc: r.Desc,
Label: r.Label,
Template: r.Template,
PackageName: r.PackageName,
Module: global.GVA_CONFIG.AutoCode.Module,
}
}

View File

@@ -0,0 +1,57 @@
package request
import (
common "git.echol.cn/loser/st/server/model/common/request"
model "git.echol.cn/loser/st/server/model/system"
)
type SysAutoHistoryCreate struct {
Table string // 表名
Package string // 模块名/插件名
Request string // 前端传入的结构化信息
StructName string // 结构体名称
BusinessDB string // 业务库
Description string // Struct中文名称
Injections map[string]string // 注入路径
Templates map[string]string // 模板信息
ApiIDs []uint // api表注册内容
MenuID uint // 菜单ID
ExportTemplateID uint // 导出模板ID
}
func (r *SysAutoHistoryCreate) Create() model.SysAutoCodeHistory {
entity := model.SysAutoCodeHistory{
Package: r.Package,
Request: r.Request,
Table: r.Table,
StructName: r.StructName,
Abbreviation: r.StructName,
BusinessDB: r.BusinessDB,
Description: r.Description,
Injections: r.Injections,
Templates: r.Templates,
ApiIDs: r.ApiIDs,
MenuID: r.MenuID,
ExportTemplateID: r.ExportTemplateID,
}
if entity.Table == "" {
entity.Table = r.StructName
}
return entity
}
type SysAutoHistoryRollBack struct {
common.GetById
DeleteApi bool `json:"deleteApi" form:"deleteApi"` // 是否删除接口
DeleteMenu bool `json:"deleteMenu" form:"deleteMenu"` // 是否删除菜单
DeleteTable bool `json:"deleteTable" form:"deleteTable"` // 是否删除表
}
func (r *SysAutoHistoryRollBack) ApiIds(entity model.SysAutoCodeHistory) common.IdsReq {
length := len(entity.ApiIDs)
ids := make([]int, 0)
for i := 0; i < length; i++ {
ids = append(ids, int(entity.ApiIDs[i]))
}
return common.IdsReq{Ids: ids}
}

View File

@@ -0,0 +1,27 @@
package request
// CasbinInfo Casbin info structure
type CasbinInfo struct {
Path string `json:"path"` // 路径
Method string `json:"method"` // 方法
}
// CasbinInReceive Casbin structure for input parameters
type CasbinInReceive struct {
AuthorityId uint `json:"authorityId"` // 权限id
CasbinInfos []CasbinInfo `json:"casbinInfos"`
}
func DefaultCasbin() []CasbinInfo {
return []CasbinInfo{
{Path: "/menu/getMenu", Method: "POST"},
{Path: "/jwt/jsonInBlacklist", Method: "POST"},
{Path: "/base/login", Method: "POST"},
{Path: "/user/changePassword", Method: "POST"},
{Path: "/user/setUserAuthority", Method: "POST"},
{Path: "/user/getUserInfo", Method: "GET"},
{Path: "/user/setSelfInfo", Method: "PUT"},
{Path: "/fileUploadAndDownload/upload", Method: "POST"},
{Path: "/sysDictionary/findSysDictionary", Method: "GET"},
}
}

View File

@@ -0,0 +1,9 @@
package request
type SysDictionarySearch struct {
Name string `json:"name" form:"name" gorm:"column:name;comment:字典名(中)"` // 字典名(中)
}
type ImportSysDictionaryRequest struct {
Json string `json:"json" binding:"required"` // JSON字符串
}

View File

@@ -0,0 +1,43 @@
package request
import (
"git.echol.cn/loser/st/server/model/common/request"
"git.echol.cn/loser/st/server/model/system"
)
type SysDictionaryDetailSearch struct {
system.SysDictionaryDetail
request.PageInfo
ParentID *uint `json:"parentID" form:"parentID"` // 父级字典详情ID用于查询指定父级下的子项
Level *int `json:"level" form:"level"` // 层级深度,用于查询指定层级的数据
}
// CreateSysDictionaryDetailRequest 创建字典详情请求
type CreateSysDictionaryDetailRequest struct {
Label string `json:"label" form:"label" binding:"required"` // 展示值
Value string `json:"value" form:"value" binding:"required"` // 字典值
Extend string `json:"extend" form:"extend"` // 扩展值
Status *bool `json:"status" form:"status"` // 启用状态
Sort int `json:"sort" form:"sort"` // 排序标记
SysDictionaryID int `json:"sysDictionaryID" form:"sysDictionaryID" binding:"required"` // 关联标记
ParentID *uint `json:"parentID" form:"parentID"` // 父级字典详情ID
}
// UpdateSysDictionaryDetailRequest 更新字典详情请求
type UpdateSysDictionaryDetailRequest struct {
ID uint `json:"ID" form:"ID" binding:"required"` // 主键ID
Label string `json:"label" form:"label" binding:"required"` // 展示值
Value string `json:"value" form:"value" binding:"required"` // 字典值
Extend string `json:"extend" form:"extend"` // 扩展值
Status *bool `json:"status" form:"status"` // 启用状态
Sort int `json:"sort" form:"sort"` // 排序标记
SysDictionaryID int `json:"sysDictionaryID" form:"sysDictionaryID" binding:"required"` // 关联标记
ParentID *uint `json:"parentID" form:"parentID"` // 父级字典详情ID
}
// GetDictionaryDetailsByParentRequest 根据父级ID获取字典详情请求
type GetDictionaryDetailsByParentRequest struct {
SysDictionaryID int `json:"sysDictionaryID" form:"sysDictionaryID" binding:"required"` // 字典ID
ParentID *uint `json:"parentID" form:"parentID"` // 父级字典详情ID为空时获取顶级
IncludeChildren bool `json:"includeChildren" form:"includeChildren"` // 是否包含子级数据
}

View File

@@ -0,0 +1,14 @@
package request
import (
"time"
"git.echol.cn/loser/st/server/model/common/request"
)
type SysErrorSearch struct {
CreatedAtRange []time.Time `json:"createdAtRange" form:"createdAtRange[]"`
Form *string `json:"form" form:"form"`
Info *string `json:"info" form:"info"`
request.PageInfo
}

View File

@@ -0,0 +1,15 @@
package request
import (
"time"
"git.echol.cn/loser/st/server/model/common/request"
"git.echol.cn/loser/st/server/model/system"
)
type SysExportTemplateSearch struct {
system.SysExportTemplate
StartCreatedAt *time.Time `json:"startCreatedAt" form:"startCreatedAt"`
EndCreatedAt *time.Time `json:"endCreatedAt" form:"endCreatedAt"`
request.PageInfo
}

View File

@@ -0,0 +1,125 @@
package request
import (
"fmt"
"os"
"git.echol.cn/loser/st/server/config"
)
type InitDB struct {
AdminPassword string `json:"adminPassword" binding:"required"`
DBType string `json:"dbType"` // 数据库类型
Host string `json:"host"` // 服务器地址
Port string `json:"port"` // 数据库连接端口
UserName string `json:"userName"` // 数据库用户名
Password string `json:"password"` // 数据库密码
DBName string `json:"dbName" binding:"required"` // 数据库名
DBPath string `json:"dbPath"` // sqlite数据库文件路径
Template string `json:"template"` // postgresql指定template
}
// MysqlEmptyDsn msyql 空数据库 建库链接
// Author SliverHorn
func (i *InitDB) MysqlEmptyDsn() string {
if i.Host == "" {
i.Host = "127.0.0.1"
}
if i.Port == "" {
i.Port = "3306"
}
return fmt.Sprintf("%s:%s@tcp(%s:%s)/", i.UserName, i.Password, i.Host, i.Port)
}
// PgsqlEmptyDsn pgsql 空数据库 建库链接
// Author SliverHorn
func (i *InitDB) PgsqlEmptyDsn() string {
if i.Host == "" {
i.Host = "127.0.0.1"
}
if i.Port == "" {
i.Port = "5432"
}
return "host=" + i.Host + " user=" + i.UserName + " password=" + i.Password + " port=" + i.Port + " dbname=" + "postgres" + " " + "sslmode=disable TimeZone=Asia/Shanghai"
}
// SqliteEmptyDsn sqlite 空数据库 建库链接
// Author Kafumio
func (i *InitDB) SqliteEmptyDsn() string {
separator := string(os.PathSeparator)
return i.DBPath + separator + i.DBName + ".db"
}
func (i *InitDB) MssqlEmptyDsn() string {
return "sqlserver://" + i.UserName + ":" + i.Password + "@" + i.Host + ":" + i.Port + "?database=" + i.DBName + "&encrypt=disable"
}
// ToMysqlConfig 转换 config.Mysql
// Author [SliverHorn](https://github.com/SliverHorn)
func (i *InitDB) ToMysqlConfig() config.Mysql {
return config.Mysql{
GeneralDB: config.GeneralDB{
Path: i.Host,
Port: i.Port,
Dbname: i.DBName,
Username: i.UserName,
Password: i.Password,
MaxIdleConns: 10,
MaxOpenConns: 100,
LogMode: "error",
Config: "charset=utf8mb4&parseTime=True&loc=Local",
},
}
}
// ToPgsqlConfig 转换 config.Pgsql
// Author [SliverHorn](https://github.com/SliverHorn)
func (i *InitDB) ToPgsqlConfig() config.Pgsql {
return config.Pgsql{
GeneralDB: config.GeneralDB{
Path: i.Host,
Port: i.Port,
Dbname: i.DBName,
Username: i.UserName,
Password: i.Password,
MaxIdleConns: 10,
MaxOpenConns: 100,
LogMode: "error",
Config: "sslmode=disable TimeZone=Asia/Shanghai",
},
}
}
// ToSqliteConfig 转换 config.Sqlite
// Author [Kafumio](https://github.com/Kafumio)
func (i *InitDB) ToSqliteConfig() config.Sqlite {
return config.Sqlite{
GeneralDB: config.GeneralDB{
Path: i.DBPath,
Port: i.Port,
Dbname: i.DBName,
Username: i.UserName,
Password: i.Password,
MaxIdleConns: 10,
MaxOpenConns: 100,
LogMode: "error",
Config: "",
},
}
}
func (i *InitDB) ToMssqlConfig() config.Mssql {
return config.Mssql{
GeneralDB: config.GeneralDB{
Path: i.DBPath,
Port: i.Port,
Dbname: i.DBName,
Username: i.UserName,
Password: i.Password,
MaxIdleConns: 10,
MaxOpenConns: 100,
LogMode: "error",
Config: "",
},
}
}

View File

@@ -0,0 +1,11 @@
package request
import (
"git.echol.cn/loser/st/server/model/common/request"
"git.echol.cn/loser/st/server/model/system"
)
type SysLoginLogSearch struct {
system.SysLoginLog
request.PageInfo
}

View File

@@ -0,0 +1,27 @@
package request
import (
"git.echol.cn/loser/st/server/global"
"git.echol.cn/loser/st/server/model/system"
)
// AddMenuAuthorityInfo Add menu authority info structure
type AddMenuAuthorityInfo struct {
Menus []system.SysBaseMenu `json:"menus"`
AuthorityId uint `json:"authorityId"` // 角色ID
}
func DefaultMenu() []system.SysBaseMenu {
return []system.SysBaseMenu{{
GVA_MODEL: global.GVA_MODEL{ID: 1},
ParentId: 0,
Path: "dashboard",
Name: "dashboard",
Component: "view/dashboard/index.vue",
Sort: 1,
Meta: system.Meta{
Title: "仪表盘",
Icon: "setting",
},
}}
}

View File

@@ -0,0 +1,11 @@
package request
import (
"git.echol.cn/loser/st/server/model/common/request"
"git.echol.cn/loser/st/server/model/system"
)
type SysOperationRecordSearch struct {
system.SysOperationRecord
request.PageInfo
}

View File

@@ -0,0 +1,15 @@
package request
import (
"time"
"git.echol.cn/loser/st/server/model/common/request"
)
type SysParamsSearch struct {
StartCreatedAt *time.Time `json:"startCreatedAt" form:"startCreatedAt"`
EndCreatedAt *time.Time `json:"endCreatedAt" form:"endCreatedAt"`
Name string `json:"name" form:"name" `
Key string `json:"key" form:"key" `
request.PageInfo
}

View File

@@ -0,0 +1,64 @@
package request
import "git.echol.cn/loser/st/server/model/system"
type SkillToolRequest struct {
Tool string `json:"tool"`
}
type SkillDetailRequest struct {
Tool string `json:"tool"`
Skill string `json:"skill"`
}
type SkillSaveRequest struct {
Tool string `json:"tool"`
Skill string `json:"skill"`
Meta system.SkillMeta `json:"meta"`
Markdown string `json:"markdown"`
SyncTools []string `json:"syncTools"`
}
type SkillScriptCreateRequest struct {
Tool string `json:"tool"`
Skill string `json:"skill"`
FileName string `json:"fileName"`
ScriptType string `json:"scriptType"`
}
type SkillResourceCreateRequest struct {
Tool string `json:"tool"`
Skill string `json:"skill"`
FileName string `json:"fileName"`
}
type SkillReferenceCreateRequest struct {
Tool string `json:"tool"`
Skill string `json:"skill"`
FileName string `json:"fileName"`
}
type SkillTemplateCreateRequest struct {
Tool string `json:"tool"`
Skill string `json:"skill"`
FileName string `json:"fileName"`
}
type SkillFileRequest struct {
Tool string `json:"tool"`
Skill string `json:"skill"`
FileName string `json:"fileName"`
}
type SkillFileSaveRequest struct {
Tool string `json:"tool"`
Skill string `json:"skill"`
FileName string `json:"fileName"`
Content string `json:"content"`
}
type SkillGlobalConstraintSaveRequest struct {
Tool string `json:"tool"`
Content string `json:"content"`
SyncTools []string `json:"syncTools"`
}

View File

@@ -0,0 +1,69 @@
package request
import (
common "git.echol.cn/loser/st/server/model/common/request"
"git.echol.cn/loser/st/server/model/system"
)
// Register User register structure
type Register struct {
Username string `json:"userName" example:"用户名"`
Password string `json:"passWord" example:"密码"`
NickName string `json:"nickName" example:"昵称"`
HeaderImg string `json:"headerImg" example:"头像链接"`
AuthorityId uint `json:"authorityId" swaggertype:"string" example:"int 角色id"`
Enable int `json:"enable" swaggertype:"string" example:"int 是否启用"`
AuthorityIds []uint `json:"authorityIds" swaggertype:"string" example:"[]uint 角色id"`
Phone string `json:"phone" example:"电话号码"`
Email string `json:"email" example:"电子邮箱"`
}
// Login User login structure
type Login struct {
Username string `json:"username"` // 用户名
Password string `json:"password"` // 密码
Captcha string `json:"captcha"` // 验证码
CaptchaId string `json:"captchaId"` // 验证码ID
}
// ChangePasswordReq Modify password structure
type ChangePasswordReq struct {
ID uint `json:"-"` // 从 JWT 中提取 user id避免越权
Password string `json:"password"` // 密码
NewPassword string `json:"newPassword"` // 新密码
}
type ResetPassword struct {
ID uint `json:"ID" form:"ID"`
Password string `json:"password" form:"password" gorm:"comment:用户登录密码"` // 用户登录密码
}
// SetUserAuth Modify user's auth structure
type SetUserAuth struct {
AuthorityId uint `json:"authorityId"` // 角色ID
}
// SetUserAuthorities Modify user's auth structure
type SetUserAuthorities struct {
ID uint
AuthorityIds []uint `json:"authorityIds"` // 角色ID
}
type ChangeUserInfo struct {
ID uint `gorm:"primarykey"` // 主键ID
NickName string `json:"nickName" gorm:"default:系统用户;comment:用户昵称"` // 用户昵称
Phone string `json:"phone" gorm:"comment:用户手机号"` // 用户手机号
AuthorityIds []uint `json:"authorityIds" gorm:"-"` // 角色ID
Email string `json:"email" gorm:"comment:用户邮箱"` // 用户邮箱
HeaderImg string `json:"headerImg" gorm:"default:https://qmplusimg.henrongyi.top/gva_header.jpg;comment:用户头像"` // 用户头像
Enable int `json:"enable" gorm:"comment:冻结用户"` //冻结用户
Authorities []system.SysAuthority `json:"-" gorm:"many2many:sys_user_authority;"`
}
type GetUserList struct {
common.PageInfo
Username string `json:"username" form:"username"`
NickName string `json:"nickName" form:"nickName"`
Phone string `json:"phone" form:"phone"`
Email string `json:"email" form:"email"`
}

View File

@@ -0,0 +1,41 @@
package request
import (
"time"
"git.echol.cn/loser/st/server/model/common/request"
"git.echol.cn/loser/st/server/model/system"
)
type SysVersionSearch struct {
CreatedAtRange []time.Time `json:"createdAtRange" form:"createdAtRange[]"`
VersionName *string `json:"versionName" form:"versionName"`
VersionCode *string `json:"versionCode" form:"versionCode"`
request.PageInfo
}
// ExportVersionRequest 导出版本请求结构体
type ExportVersionRequest struct {
VersionName string `json:"versionName" binding:"required"` // 版本名称
VersionCode string `json:"versionCode" binding:"required"` // 版本号
Description string `json:"description"` // 版本描述
MenuIds []uint `json:"menuIds"` // 选中的菜单ID列表
ApiIds []uint `json:"apiIds"` // 选中的API ID列表
DictIds []uint `json:"dictIds"` // 选中的字典ID列表
}
// ImportVersionRequest 导入版本请求结构体
type ImportVersionRequest struct {
VersionInfo VersionInfo `json:"version" binding:"required"` // 版本信息
ExportMenu []system.SysBaseMenu `json:"menus"` // 菜单数据直接复用SysBaseMenu
ExportApi []system.SysApi `json:"apis"` // API数据直接复用SysApi
ExportDictionary []system.SysDictionary `json:"dictionaries"` // 字典数据直接复用SysDictionary
}
// VersionInfo 版本信息结构体
type VersionInfo struct {
Name string `json:"name" binding:"required"` // 版本名称
Code string `json:"code" binding:"required"` // 版本号
Description string `json:"description"` // 版本描述
ExportTime string `json:"exportTime"` // 导出时间
}

View File

@@ -0,0 +1,18 @@
package response
import (
"git.echol.cn/loser/st/server/model/system"
)
type SysAPIResponse struct {
Api system.SysApi `json:"api"`
}
type SysAPIListResponse struct {
Apis []system.SysApi `json:"apis"`
}
type SysSyncApis struct {
NewApis []system.SysApi `json:"newApis"`
DeleteApis []system.SysApi `json:"deleteApis"`
}

View File

@@ -0,0 +1,12 @@
package response
import "git.echol.cn/loser/st/server/model/system"
type SysAuthorityResponse struct {
Authority system.SysAuthority `json:"authority"`
}
type SysAuthorityCopyResponse struct {
Authority system.SysAuthority `json:"authority"`
OldAuthorityId uint `json:"oldAuthorityId"` // 旧角色ID
}

View File

@@ -0,0 +1,5 @@
package response
type SysAuthorityBtnRes struct {
Selected []uint `json:"selected"`
}

View File

@@ -0,0 +1,27 @@
package response
import "git.echol.cn/loser/st/server/model/system"
type Db struct {
Database string `json:"database" gorm:"column:database"`
}
type Table struct {
TableName string `json:"tableName" gorm:"column:table_name"`
}
type Column struct {
DataType string `json:"dataType" gorm:"column:data_type"`
ColumnName string `json:"columnName" gorm:"column:column_name"`
DataTypeLong string `json:"dataTypeLong" gorm:"column:data_type_long"`
ColumnComment string `json:"columnComment" gorm:"column:column_comment"`
PrimaryKey bool `json:"primaryKey" gorm:"column:primary_key"`
}
type PluginInfo struct {
PluginName string `json:"pluginName"`
PluginType string `json:"pluginType"` // web, server, full
Apis []system.SysApi `json:"apis"`
Menus []system.SysBaseMenu `json:"menus"`
Dictionaries []system.SysDictionary `json:"dictionaries"`
}

View File

@@ -0,0 +1,8 @@
package response
type SysCaptchaResponse struct {
CaptchaId string `json:"captchaId"`
PicPath string `json:"picPath"`
CaptchaLength int `json:"captchaLength"`
OpenCaptcha bool `json:"openCaptcha"`
}

View File

@@ -0,0 +1,9 @@
package response
import (
"git.echol.cn/loser/st/server/model/system/request"
)
type PolicyPathResponse struct {
Paths []request.CasbinInfo `json:"paths"`
}

View File

@@ -0,0 +1,15 @@
package response
import "git.echol.cn/loser/st/server/model/system"
type SysMenusResponse struct {
Menus []system.SysMenu `json:"menus"`
}
type SysBaseMenusResponse struct {
Menus []system.SysBaseMenu `json:"menus"`
}
type SysBaseMenuResponse struct {
Menu system.SysBaseMenu `json:"menu"`
}

View File

@@ -0,0 +1,7 @@
package response
import "git.echol.cn/loser/st/server/config"
type SysConfigResponse struct {
Config config.Server `json:"config"`
}

View File

@@ -0,0 +1,15 @@
package response
import (
"git.echol.cn/loser/st/server/model/system"
)
type SysUserResponse struct {
User system.SysUser `json:"user"`
}
type LoginResponse struct {
User system.SysUser `json:"user"`
Token string `json:"token"`
ExpiresAt int64 `json:"expiresAt"`
}

View File

@@ -0,0 +1,14 @@
package response
import (
"git.echol.cn/loser/st/server/model/system"
"git.echol.cn/loser/st/server/model/system/request"
)
// ExportVersionResponse 导出版本响应结构体
type ExportVersionResponse struct {
Version request.VersionInfo `json:"version"` // 版本信息
Menus []system.SysBaseMenu `json:"menus"` // 菜单数据直接复用SysBaseMenu
Apis []system.SysApi `json:"apis"` // API数据直接复用SysApi
Dictionaries []system.SysDictionary `json:"dictionaries"` // 字典数据直接复用SysDictionary
}

View File

@@ -0,0 +1,28 @@
package system
import (
"git.echol.cn/loser/st/server/global"
)
type SysApi struct {
global.GVA_MODEL
Path string `json:"path" gorm:"comment:api路径"` // api路径
Description string `json:"description" gorm:"comment:api中文描述"` // api中文描述
ApiGroup string `json:"apiGroup" gorm:"comment:api组"` // api组
Method string `json:"method" gorm:"default:POST;comment:方法"` // 方法:创建POST(默认)|查看GET|更新PUT|删除DELETE
}
func (SysApi) TableName() string {
return "sys_apis"
}
type SysIgnoreApi struct {
global.GVA_MODEL
Path string `json:"path" gorm:"comment:api路径"` // api路径
Method string `json:"method" gorm:"default:POST;comment:方法"` // 方法:创建POST(默认)|查看GET|更新PUT|删除DELETE
Flag bool `json:"flag" gorm:"-"` // 是否忽略
}
func (SysIgnoreApi) TableName() string {
return "sys_ignore_apis"
}

View File

@@ -0,0 +1,18 @@
package system
import (
"time"
"git.echol.cn/loser/st/server/global"
)
type SysApiToken struct {
global.GVA_MODEL
UserID uint `json:"userId" gorm:"comment:用户ID"`
User SysUser `json:"user" gorm:"foreignKey:UserID;"`
AuthorityID uint `json:"authorityId" gorm:"comment:角色ID"`
Token string `json:"token" gorm:"type:text;comment:Token"`
Status bool `json:"status" gorm:"default:true;comment:状态"` // true有效 false无效
ExpiresAt time.Time `json:"expiresAt" gorm:"comment:过期时间"`
Remark string `json:"remark" gorm:"comment:备注"`
}

View File

@@ -0,0 +1,23 @@
package system
import (
"time"
)
type SysAuthority struct {
CreatedAt time.Time // 创建时间
UpdatedAt time.Time // 更新时间
DeletedAt *time.Time `sql:"index"`
AuthorityId uint `json:"authorityId" gorm:"not null;unique;primary_key;comment:角色ID;size:90"` // 角色ID
AuthorityName string `json:"authorityName" gorm:"comment:角色名"` // 角色名
ParentId *uint `json:"parentId" gorm:"comment:父角色ID"` // 父角色ID
DataAuthorityId []*SysAuthority `json:"dataAuthorityId" gorm:"many2many:sys_data_authority_id;"`
Children []SysAuthority `json:"children" gorm:"-"`
SysBaseMenus []SysBaseMenu `json:"menus" gorm:"many2many:sys_authority_menus;"`
Users []SysUser `json:"-" gorm:"many2many:sys_user_authority;"`
DefaultRouter string `json:"defaultRouter" gorm:"comment:默认菜单;default:dashboard"` // 默认菜单(默认dashboard)
}
func (SysAuthority) TableName() string {
return "sys_authorities"
}

View File

@@ -0,0 +1,8 @@
package system
type SysAuthorityBtn struct {
AuthorityId uint `gorm:"comment:角色ID"`
SysMenuID uint `gorm:"comment:菜单ID"`
SysBaseMenuBtnID uint `gorm:"comment:菜单按钮ID"`
SysBaseMenuBtn SysBaseMenuBtn ` gorm:"comment:按钮详情"`
}

View File

@@ -0,0 +1,19 @@
package system
type SysMenu struct {
SysBaseMenu
MenuId uint `json:"menuId" gorm:"comment:菜单ID"`
AuthorityId uint `json:"-" gorm:"comment:角色ID"`
Children []SysMenu `json:"children" gorm:"-"`
Parameters []SysBaseMenuParameter `json:"parameters" gorm:"foreignKey:SysBaseMenuID;references:MenuId"`
Btns map[string]uint `json:"btns" gorm:"-"`
}
type SysAuthorityMenu struct {
MenuId string `json:"menuId" gorm:"comment:菜单ID;column:sys_base_menu_id"`
AuthorityId string `json:"-" gorm:"comment:角色ID;column:sys_authority_authority_id"`
}
func (s SysAuthorityMenu) TableName() string {
return "sys_authority_menus"
}

View File

@@ -0,0 +1,69 @@
package system
import (
"os"
"path"
"path/filepath"
"strings"
"git.echol.cn/loser/st/server/global"
"gorm.io/gorm"
)
// SysAutoCodeHistory 自动迁移代码记录,用于回滚,重放使用
type SysAutoCodeHistory struct {
global.GVA_MODEL
Table string `json:"tableName" gorm:"column:table_name;comment:表名"`
Package string `json:"package" gorm:"column:package;comment:模块名/插件名"`
Request string `json:"request" gorm:"type:text;column:request;comment:前端传入的结构化信息"`
StructName string `json:"structName" gorm:"column:struct_name;comment:结构体名称"`
Abbreviation string `json:"abbreviation" gorm:"column:abbreviation;comment:结构体名称缩写"`
BusinessDB string `json:"businessDb" gorm:"column:business_db;comment:业务库"`
Description string `json:"description" gorm:"column:description;comment:Struct中文名称"`
Templates map[string]string `json:"template" gorm:"serializer:json;type:text;column:templates;comment:模板信息"`
Injections map[string]string `json:"injections" gorm:"serializer:json;type:text;column:Injections;comment:注入路径"`
Flag int `json:"flag" gorm:"column:flag;comment:[0:创建,1:回滚]"`
ApiIDs []uint `json:"apiIDs" gorm:"serializer:json;column:api_ids;comment:api表注册内容"`
MenuID uint `json:"menuId" gorm:"column:menu_id;comment:菜单ID"`
ExportTemplateID uint `json:"exportTemplateID" gorm:"column:export_template_id;comment:导出模板ID"`
AutoCodePackage SysAutoCodePackage `json:"autoCodePackage" gorm:"foreignKey:ID;references:PackageID"`
PackageID uint `json:"packageID" gorm:"column:package_id;comment:包ID"`
}
func (s *SysAutoCodeHistory) BeforeCreate(db *gorm.DB) error {
templates := make(map[string]string, len(s.Templates))
for key, value := range s.Templates {
server := filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server)
{
hasServer := strings.Index(key, server)
if hasServer != -1 {
key = strings.TrimPrefix(key, server)
keys := strings.Split(key, string(os.PathSeparator))
key = path.Join(keys...)
}
} // key
web := filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.WebRoot())
hasWeb := strings.Index(value, web)
if hasWeb != -1 {
value = strings.TrimPrefix(value, web)
values := strings.Split(value, string(os.PathSeparator))
value = path.Join(values...)
templates[key] = value
continue
}
hasServer := strings.Index(value, server)
if hasServer != -1 {
value = strings.TrimPrefix(value, server)
values := strings.Split(value, string(os.PathSeparator))
value = path.Join(values...)
templates[key] = value
continue
}
}
s.Templates = templates
return nil
}
func (s *SysAutoCodeHistory) TableName() string {
return "sys_auto_code_histories"
}

View File

@@ -0,0 +1,18 @@
package system
import (
"git.echol.cn/loser/st/server/global"
)
type SysAutoCodePackage struct {
global.GVA_MODEL
Desc string `json:"desc" gorm:"comment:描述"`
Label string `json:"label" gorm:"comment:展示名"`
Template string `json:"template" gorm:"comment:模版"`
PackageName string `json:"packageName" gorm:"comment:包名"`
Module string `json:"-" example:"模块"`
}
func (s *SysAutoCodePackage) TableName() string {
return "sys_auto_code_packages"
}

View File

@@ -0,0 +1,43 @@
package system
import (
"git.echol.cn/loser/st/server/global"
)
type SysBaseMenu struct {
global.GVA_MODEL
MenuLevel uint `json:"-"`
ParentId uint `json:"parentId" gorm:"comment:父菜单ID"` // 父菜单ID
Path string `json:"path" gorm:"comment:路由path"` // 路由path
Name string `json:"name" gorm:"comment:路由name"` // 路由name
Hidden bool `json:"hidden" gorm:"comment:是否在列表隐藏"` // 是否在列表隐藏
Component string `json:"component" gorm:"comment:对应前端文件路径"` // 对应前端文件路径
Sort int `json:"sort" gorm:"comment:排序标记"` // 排序标记
Meta `json:"meta" gorm:"embedded"` // 附加属性
SysAuthoritys []SysAuthority `json:"authoritys" gorm:"many2many:sys_authority_menus;"`
Children []SysBaseMenu `json:"children" gorm:"-"`
Parameters []SysBaseMenuParameter `json:"parameters"`
MenuBtn []SysBaseMenuBtn `json:"menuBtn"`
}
type Meta struct {
ActiveName string `json:"activeName" gorm:"comment:高亮菜单"`
KeepAlive bool `json:"keepAlive" gorm:"comment:是否缓存"` // 是否缓存
DefaultMenu bool `json:"defaultMenu" gorm:"comment:是否是基础路由(开发中)"` // 是否是基础路由(开发中)
Title string `json:"title" gorm:"comment:菜单名"` // 菜单名
Icon string `json:"icon" gorm:"comment:菜单图标"` // 菜单图标
CloseTab bool `json:"closeTab" gorm:"comment:自动关闭tab"` // 自动关闭tab
TransitionType string `json:"transitionType" gorm:"comment:路由切换动画"` // 路由切换动画
}
type SysBaseMenuParameter struct {
global.GVA_MODEL
SysBaseMenuID uint
Type string `json:"type" gorm:"comment:地址栏携带参数为params还是query"` // 地址栏携带参数为params还是query
Key string `json:"key" gorm:"comment:地址栏携带参数的key"` // 地址栏携带参数的key
Value string `json:"value" gorm:"comment:地址栏携带参数的值"` // 地址栏携带参数的值
}
func (SysBaseMenu) TableName() string {
return "sys_base_menus"
}

View File

@@ -0,0 +1,22 @@
// 自动生成模板SysDictionary
package system
import (
"git.echol.cn/loser/st/server/global"
)
// 如果含有time.Time 请自行import time包
type SysDictionary struct {
global.GVA_MODEL
Name string `json:"name" form:"name" gorm:"column:name;comment:字典名(中)"` // 字典名(中)
Type string `json:"type" form:"type" gorm:"column:type;comment:字典名(英)"` // 字典名(英)
Status *bool `json:"status" form:"status" gorm:"column:status;comment:状态"` // 状态
Desc string `json:"desc" form:"desc" gorm:"column:desc;comment:描述"` // 描述
ParentID *uint `json:"parentID" form:"parentID" gorm:"column:parent_id;comment:父级字典ID"` // 父级字典ID
Children []SysDictionary `json:"children" gorm:"foreignKey:ParentID"` // 子字典
SysDictionaryDetails []SysDictionaryDetail `json:"sysDictionaryDetails" form:"sysDictionaryDetails"`
}
func (SysDictionary) TableName() string {
return "sys_dictionaries"
}

View File

@@ -0,0 +1,26 @@
// 自动生成模板SysDictionaryDetail
package system
import (
"git.echol.cn/loser/st/server/global"
)
// 如果含有time.Time 请自行import time包
type SysDictionaryDetail struct {
global.GVA_MODEL
Label string `json:"label" form:"label" gorm:"column:label;comment:展示值"` // 展示值
Value string `json:"value" form:"value" gorm:"column:value;comment:字典值"` // 字典值
Extend string `json:"extend" form:"extend" gorm:"column:extend;comment:扩展值"` // 扩展值
Status *bool `json:"status" form:"status" gorm:"column:status;comment:启用状态"` // 启用状态
Sort int `json:"sort" form:"sort" gorm:"column:sort;comment:排序标记"` // 排序标记
SysDictionaryID int `json:"sysDictionaryID" form:"sysDictionaryID" gorm:"column:sys_dictionary_id;comment:关联标记"` // 关联标记
ParentID *uint `json:"parentID" form:"parentID" gorm:"column:parent_id;comment:父级字典详情ID"` // 父级字典详情ID
Children []SysDictionaryDetail `json:"children" gorm:"foreignKey:ParentID"` // 子字典详情
Level int `json:"level" form:"level" gorm:"column:level;comment:层级深度"` // 层级深度从0开始
Path string `json:"path" form:"path" gorm:"column:path;comment:层级路径"` // 层级路径,如 "1,2,3"
Disabled bool `json:"disabled" gorm:"-"` // 禁用状态根据status字段动态计算
}
func (SysDictionaryDetail) TableName() string {
return "sys_dictionary_details"
}

View File

@@ -0,0 +1,21 @@
// 自动生成模板SysError
package system
import (
"git.echol.cn/loser/st/server/global"
)
// 错误日志 结构体 SysError
type SysError struct {
global.GVA_MODEL
Form *string `json:"form" form:"form" gorm:"comment:错误来源;column:form;type:text;" binding:"required"` //错误来源
Info *string `json:"info" form:"info" gorm:"comment:错误内容;column:info;type:text;"` //错误内容
Level string `json:"level" form:"level" gorm:"comment:日志等级;column:level;"`
Solution *string `json:"solution" form:"solution" gorm:"comment:解决方案;column:solution;type:text"` //解决方案
Status string `json:"status" form:"status" gorm:"comment:处理状态;column:status;type:varchar(20);default:未处理;"` //处理状态:未处理/处理中/处理完成
}
// TableName 错误日志 SysError自定义表名 sys_error
func (SysError) TableName() string {
return "sys_error"
}

View File

@@ -0,0 +1,46 @@
// 自动生成模板SysExportTemplate
package system
import (
"git.echol.cn/loser/st/server/global"
)
// 导出模板 结构体 SysExportTemplate
type SysExportTemplate struct {
global.GVA_MODEL
DBName string `json:"dbName" form:"dbName" gorm:"column:db_name;comment:数据库名称;"` //数据库名称
Name string `json:"name" form:"name" gorm:"column:name;comment:模板名称;"` //模板名称
TableName string `json:"tableName" form:"tableName" gorm:"column:table_name;comment:表名称;"` //表名称
TemplateID string `json:"templateID" form:"templateID" gorm:"column:template_id;comment:模板标识;"` //模板标识
TemplateInfo string `json:"templateInfo" form:"templateInfo" gorm:"column:template_info;type:text;"` //模板信息
SQL string `json:"sql" form:"sql" gorm:"column:sql;type:text;comment:自定义导出SQL;"` //自定义导出SQL
ImportSQL string `json:"importSql" form:"importSql" gorm:"column:import_sql;type:text;comment:自定义导入SQL;"` //自定义导入SQL
Limit *int `json:"limit" form:"limit" gorm:"column:limit;comment:导出限制"`
Order string `json:"order" form:"order" gorm:"column:order;comment:排序"`
Conditions []Condition `json:"conditions" form:"conditions" gorm:"foreignKey:TemplateID;references:TemplateID;comment:条件"`
JoinTemplate []JoinTemplate `json:"joinTemplate" form:"joinTemplate" gorm:"foreignKey:TemplateID;references:TemplateID;comment:关联"`
}
type JoinTemplate struct {
global.GVA_MODEL
TemplateID string `json:"templateID" form:"templateID" gorm:"column:template_id;comment:模板标识"`
JOINS string `json:"joins" form:"joins" gorm:"column:joins;comment:关联"`
Table string `json:"table" form:"table" gorm:"column:table;comment:关联表"`
ON string `json:"on" form:"on" gorm:"column:on;comment:关联条件"`
}
func (JoinTemplate) TableName() string {
return "sys_export_template_join"
}
type Condition struct {
global.GVA_MODEL
TemplateID string `json:"templateID" form:"templateID" gorm:"column:template_id;comment:模板标识"`
From string `json:"from" form:"from" gorm:"column:from;comment:条件取的key"`
Column string `json:"column" form:"column" gorm:"column:column;comment:作为查询条件的字段"`
Operator string `json:"operator" form:"operator" gorm:"column:operator;comment:操作符"`
}
func (Condition) TableName() string {
return "sys_export_template_condition"
}

View File

@@ -0,0 +1,10 @@
package system
import (
"git.echol.cn/loser/st/server/global"
)
type JwtBlacklist struct {
global.GVA_MODEL
Jwt string `gorm:"type:text;comment:jwt"`
}

View File

@@ -0,0 +1,16 @@
package system
import (
"git.echol.cn/loser/st/server/global"
)
type SysLoginLog struct {
global.GVA_MODEL
Username string `json:"username" gorm:"column:username;comment:用户名"`
Ip string `json:"ip" gorm:"column:ip;comment:请求ip"`
Status bool `json:"status" gorm:"column:status;comment:登录状态"`
ErrorMessage string `json:"errorMessage" gorm:"column:error_message;comment:错误信息"`
Agent string `json:"agent" gorm:"column:agent;comment:代理"`
UserID uint `json:"userId" gorm:"column:user_id;comment:用户id"`
User SysUser `json:"user" gorm:"foreignKey:UserID"`
}

View File

@@ -0,0 +1,10 @@
package system
import "git.echol.cn/loser/st/server/global"
type SysBaseMenuBtn struct {
global.GVA_MODEL
Name string `json:"name" gorm:"comment:按钮关键key"`
Desc string `json:"desc" gorm:"按钮备注"`
SysBaseMenuID uint `json:"sysBaseMenuID" gorm:"comment:菜单ID"`
}

View File

@@ -0,0 +1,24 @@
// 自动生成模板SysOperationRecord
package system
import (
"time"
"git.echol.cn/loser/st/server/global"
)
// 如果含有time.Time 请自行import time包
type SysOperationRecord struct {
global.GVA_MODEL
Ip string `json:"ip" form:"ip" gorm:"column:ip;comment:请求ip"` // 请求ip
Method string `json:"method" form:"method" gorm:"column:method;comment:请求方法"` // 请求方法
Path string `json:"path" form:"path" gorm:"column:path;comment:请求路径"` // 请求路径
Status int `json:"status" form:"status" gorm:"column:status;comment:请求状态"` // 请求状态
Latency time.Duration `json:"latency" form:"latency" gorm:"column:latency;comment:延迟" swaggertype:"string"` // 延迟
Agent string `json:"agent" form:"agent" gorm:"type:text;column:agent;comment:代理"` // 代理
ErrorMessage string `json:"error_message" form:"error_message" gorm:"column:error_message;comment:错误信息"` // 错误信息
Body string `json:"body" form:"body" gorm:"type:text;column:body;comment:请求Body"` // 请求Body
Resp string `json:"resp" form:"resp" gorm:"type:text;column:resp;comment:响应Body"` // 响应Body
UserID int `json:"user_id" form:"user_id" gorm:"column:user_id;comment:用户id"` // 用户id
User SysUser `json:"user"`
}

View File

@@ -0,0 +1,20 @@
// 自动生成模板SysParams
package system
import (
"git.echol.cn/loser/st/server/global"
)
// 参数 结构体 SysParams
type SysParams struct {
global.GVA_MODEL
Name string `json:"name" form:"name" gorm:"column:name;comment:参数名称;" binding:"required"` //参数名称
Key string `json:"key" form:"key" gorm:"column:key;comment:参数键;" binding:"required"` //参数键
Value string `json:"value" form:"value" gorm:"column:value;comment:参数值;" binding:"required"` //参数值
Desc string `json:"desc" form:"desc" gorm:"column:desc;comment:参数说明;"` //参数说明
}
// TableName 参数 SysParams自定义表名 sys_params
func (SysParams) TableName() string {
return "sys_params"
}

View File

@@ -0,0 +1,25 @@
package system
type SkillMeta struct {
Name string `json:"name" yaml:"name"`
Description string `json:"description" yaml:"description"`
AllowedTools string `json:"allowedTools" yaml:"allowed-tools,omitempty"`
Context string `json:"context" yaml:"context,omitempty"`
Agent string `json:"agent" yaml:"agent,omitempty"`
}
type SkillDetail struct {
Tool string `json:"tool"`
Skill string `json:"skill"`
Meta SkillMeta `json:"meta"`
Markdown string `json:"markdown"`
Scripts []string `json:"scripts"`
Resources []string `json:"resources"`
References []string `json:"references"`
Templates []string `json:"templates"`
}
type SkillTool struct {
Key string `json:"key"`
Label string `json:"label"`
}

View File

@@ -0,0 +1,10 @@
package system
import (
"git.echol.cn/loser/st/server/config"
)
// 配置文件结构体
type System struct {
Config config.Server `json:"config"`
}

View File

@@ -0,0 +1,62 @@
package system
import (
"git.echol.cn/loser/st/server/global"
"git.echol.cn/loser/st/server/model/common"
"github.com/google/uuid"
)
type Login interface {
GetUsername() string
GetNickname() string
GetUUID() uuid.UUID
GetUserId() uint
GetAuthorityId() uint
GetUserInfo() any
}
var _ Login = new(SysUser)
type SysUser struct {
global.GVA_MODEL
UUID uuid.UUID `json:"uuid" gorm:"index;comment:用户UUID"` // 用户UUID
Username string `json:"userName" gorm:"index;comment:用户登录名"` // 用户登录名
Password string `json:"-" gorm:"comment:用户登录密码"` // 用户登录密码
NickName string `json:"nickName" gorm:"default:系统用户;comment:用户昵称"` // 用户昵称
HeaderImg string `json:"headerImg" gorm:"default:https://qmplusimg.henrongyi.top/gva_header.jpg;comment:用户头像"` // 用户头像
AuthorityId uint `json:"authorityId" gorm:"default:888;comment:用户角色ID"` // 用户角色ID
Authority SysAuthority `json:"authority" gorm:"foreignKey:AuthorityId;references:AuthorityId;comment:用户角色"` // 用户角色
Authorities []SysAuthority `json:"authorities" gorm:"many2many:sys_user_authority;"` // 多用户角色
Phone string `json:"phone" gorm:"comment:用户手机号"` // 用户手机号
Email string `json:"email" gorm:"comment:用户邮箱"` // 用户邮箱
Enable int `json:"enable" gorm:"default:1;comment:用户是否被冻结 1正常 2冻结"` //用户是否被冻结 1正常 2冻结
OriginSetting common.JSONMap `json:"originSetting" form:"originSetting" gorm:"type:text;default:null;column:origin_setting;comment:配置;"` //配置
}
func (SysUser) TableName() string {
return "sys_users"
}
func (s *SysUser) GetUsername() string {
return s.Username
}
func (s *SysUser) GetNickname() string {
return s.NickName
}
func (s *SysUser) GetUUID() uuid.UUID {
return s.UUID
}
func (s *SysUser) GetUserId() uint {
return s.ID
}
func (s *SysUser) GetAuthorityId() uint {
return s.AuthorityId
}
func (s *SysUser) GetUserInfo() any {
return *s
}

View File

@@ -0,0 +1,11 @@
package system
// SysUserAuthority 是 sysUser 和 sysAuthority 的连接表
type SysUserAuthority struct {
SysUserId uint `gorm:"column:sys_user_id"`
SysAuthorityAuthorityId uint `gorm:"column:sys_authority_authority_id"`
}
func (s *SysUserAuthority) TableName() string {
return "sys_user_authority"
}

View File

@@ -0,0 +1,20 @@
// 自动生成模板SysVersion
package system
import (
"git.echol.cn/loser/st/server/global"
)
// 版本管理 结构体 SysVersion
type SysVersion struct {
global.GVA_MODEL
VersionName *string `json:"versionName" form:"versionName" gorm:"comment:版本名称;column:version_name;size:255;" binding:"required"` //版本名称
VersionCode *string `json:"versionCode" form:"versionCode" gorm:"comment:版本号;column:version_code;size:100;" binding:"required"` //版本号
Description *string `json:"description" form:"description" gorm:"comment:版本描述;column:description;size:500;"` //版本描述
VersionData *string `json:"versionData" form:"versionData" gorm:"comment:版本数据JSON;column:version_data;type:text;"` //版本数据
}
// TableName 版本管理 SysVersion自定义表名 sys_versions
func (SysVersion) TableName() string {
return "sys_versions"
}