搭建Go后端框架:数据模型、JWT鉴权、租户隔离、WebSocket、REST API路由
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
var DB *gorm.DB
|
||||
|
||||
func InitDB(dsn string) {
|
||||
var err error
|
||||
DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Info),
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("数据库连接失败: %v", err)
|
||||
}
|
||||
|
||||
err = DB.AutoMigrate(
|
||||
&Tenant{},
|
||||
&User{},
|
||||
&Channel{},
|
||||
&Customer{},
|
||||
&Session{},
|
||||
&Message{},
|
||||
&SessionEvent{},
|
||||
&Category{},
|
||||
&KnowledgeEntry{},
|
||||
&Plan{},
|
||||
&OperationLog{},
|
||||
&Announcement{},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("数据库迁移失败: %v", err)
|
||||
}
|
||||
|
||||
log.Println("数据库迁移完成")
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Tenant struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Name string `gorm:"size:100;not null;uniqueIndex" json:"name"`
|
||||
PlanID *uint `json:"plan_id"`
|
||||
SeatCount int `gorm:"default:2" json:"seat_count"`
|
||||
ExpireAt time.Time `json:"expire_at"`
|
||||
Status string `gorm:"size:20;default:normal" json:"status"`
|
||||
ContactName string `gorm:"size:30" json:"contact_name"`
|
||||
ContactPhone string `gorm:"size:20" json:"contact_phone"`
|
||||
ContactEmail string `gorm:"size:100" json:"contact_email"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
TenantID uint `gorm:"index;not null" json:"tenant_id"`
|
||||
Role string `gorm:"size:20;default:agent" json:"role"`
|
||||
Username string `gorm:"size:50;not null;uniqueIndex" json:"username"`
|
||||
PasswordHash string `gorm:"size:255;not null" json:"-"`
|
||||
Nickname string `gorm:"size:50" json:"nickname"`
|
||||
Status string `gorm:"size:20;default:online" json:"status"`
|
||||
LastOnlineAt *time.Time `json:"last_online_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Channel struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
TenantID uint `gorm:"index;not null" json:"tenant_id"`
|
||||
Type string `gorm:"size:30;not null" json:"type"`
|
||||
Name string `gorm:"size:50" json:"name"`
|
||||
Status string `gorm:"size:20;default:enabled" json:"status"`
|
||||
Config string `gorm:"type:text" json:"config"`
|
||||
ScriptCode string `gorm:"size:500" json:"script_code"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Customer struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
TenantID uint `gorm:"index;not null" json:"tenant_id"`
|
||||
Name string `gorm:"size:50;not null" json:"name"`
|
||||
Phone string `gorm:"size:20" json:"phone"`
|
||||
Email string `gorm:"size:100" json:"email"`
|
||||
Tags string `gorm:"type:text" json:"tags"`
|
||||
Source string `gorm:"size:30" json:"source"`
|
||||
Status string `gorm:"size:20;default:online" json:"status"`
|
||||
ConversationCount int `gorm:"default:0" json:"conversation_count"`
|
||||
SatisfactionSum float64 `gorm:"default:0" json:"-"`
|
||||
SatisfactionCount int `gorm:"default:0" json:"-"`
|
||||
LastContactAt *time.Time `json:"last_contact_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
TenantID uint `gorm:"index;not null" json:"tenant_id"`
|
||||
ChannelID uint `json:"channel_id"`
|
||||
CustomerID uint `gorm:"index" json:"customer_id"`
|
||||
AgentID *uint `gorm:"index" json:"agent_id"`
|
||||
Status string `gorm:"size:20;default:waiting" json:"status"`
|
||||
Priority string `gorm:"size:20;default:normal" json:"priority"`
|
||||
SatisfactionScore *int `json:"satisfaction_score"`
|
||||
SatisfactionText string `gorm:"size:500" json:"satisfaction_text"`
|
||||
EndReason string `gorm:"size:50" json:"end_reason"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
EndedAt *time.Time `json:"ended_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
SessionID uint `gorm:"index;not null" json:"session_id"`
|
||||
SenderType string `gorm:"size:20;not null" json:"sender_type"`
|
||||
SenderID *uint `json:"sender_id"`
|
||||
Content string `gorm:"type:text;not null" json:"content"`
|
||||
Type string `gorm:"size:20;default:text" json:"type"`
|
||||
Seq int `gorm:"not null" json:"seq"`
|
||||
SentAt time.Time `json:"sent_at"`
|
||||
}
|
||||
|
||||
type SessionEvent struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
SessionID uint `gorm:"index;not null" json:"session_id"`
|
||||
OperatorID uint `json:"operator_id"`
|
||||
Action string `gorm:"size:50;not null" json:"action"`
|
||||
Detail string `gorm:"size:500" json:"detail"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type Category struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
TenantID uint `gorm:"index;not null" json:"tenant_id"`
|
||||
ParentID *uint `json:"parent_id"`
|
||||
Name string `gorm:"size:30;not null" json:"name"`
|
||||
}
|
||||
|
||||
type KnowledgeEntry struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
TenantID uint `gorm:"index;not null" json:"tenant_id"`
|
||||
CategoryID uint `json:"category_id"`
|
||||
Title string `gorm:"size:100;not null" json:"title"`
|
||||
Content string `gorm:"type:text;not null" json:"content"`
|
||||
Status string `gorm:"size:20;default:draft" json:"status"`
|
||||
UsageCount int `gorm:"default:0" json:"usage_count"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Plan struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Name string `gorm:"size:30;not null" json:"name"`
|
||||
PriceMonthly int `json:"price_monthly"`
|
||||
Seats int `json:"seats"`
|
||||
StorageDays int `json:"storage_days"`
|
||||
KBLimit int `json:"kb_limit"`
|
||||
Features string `gorm:"type:text" json:"features"`
|
||||
Status string `gorm:"size:20;default:active" json:"status"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type OperationLog struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
OperatorID uint `json:"operator_id"`
|
||||
Action string `gorm:"size:50;not null" json:"action"`
|
||||
Detail string `gorm:"size:500" json:"detail"`
|
||||
TargetType string `gorm:"size:30" json:"target_type"`
|
||||
TargetID *uint `json:"target_id"`
|
||||
IP string `gorm:"size:50" json:"ip"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type Announcement struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Title string `gorm:"size:100;not null" json:"title"`
|
||||
Content string `gorm:"type:text" json:"content"`
|
||||
Status string `gorm:"size:20;default:draft" json:"status"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
Reference in New Issue
Block a user