Files
soul-yongping/soul-api/internal/database/database.go
2026-03-24 01:22:50 +08:00

149 lines
5.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package database
import (
"log"
"os"
"strconv"
"strings"
"time"
"soul-api/internal/model"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
var db *gorm.DB
// Init 使用 DSN 连接 MySQL供 handler 通过 DB() 使用
func Init(dsn string) error {
// 慢查询阈值:默认 5 秒,避免 GORM 默认 200ms 导致控制台刷屏;可通过 SLOW_SQL_THRESHOLD_MS 覆盖
slowMs := 5000
if s := os.Getenv("SLOW_SQL_THRESHOLD_MS"); s != "" {
if n, e := strconv.Atoi(s); e == nil && n > 0 {
slowMs = n
}
}
gormLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags),
logger.Config{
SlowThreshold: time.Duration(slowMs) * time.Millisecond,
IgnoreRecordNotFoundError: true,
Colorful: true,
},
)
var err error
db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: gormLogger})
if err != nil {
return err
}
skipMigrate := strings.ToLower(strings.TrimSpace(os.Getenv("SKIP_AUTO_MIGRATE")))
if skipMigrate == "1" || skipMigrate == "true" || skipMigrate == "yes" {
log.Println("database: SKIP_AUTO_MIGRATE enabled, skipping schema migration")
log.Println("database: connected")
return nil
}
if err := db.AutoMigrate(&model.WechatCallbackLog{}); err != nil {
log.Printf("database: wechat_callback_logs migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.Withdrawal{}); err != nil {
log.Printf("database: withdrawals migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.MatchRecord{}); err != nil {
log.Printf("database: match_records migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.UserAddress{}); err != nil {
log.Printf("database: user_addresses migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.VipRole{}); err != nil {
log.Printf("database: vip_roles migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.Order{}); err != nil {
log.Printf("database: orders migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.UserBalance{}); err != nil {
log.Printf("database: user_balances migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.BalanceTransaction{}); err != nil {
log.Printf("database: balance_transactions migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.Mentor{}); err != nil {
log.Printf("database: mentors migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.MentorConsultation{}); err != nil {
log.Printf("database: mentor_consultations migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.AuthorConfig{}); err != nil {
log.Printf("database: author_config migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.AdminUser{}); err != nil {
log.Printf("database: admin_users migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.CkbSubmitRecord{}); err != nil {
log.Printf("database: ckb_submit_records migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.CkbLeadRecord{}); err != nil {
log.Printf("database: ckb_lead_records migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.Person{}); err != nil {
log.Printf("database: persons migrate warning: %v", err)
}
// persons 历史库可能因旧索引冲突导致 AutoMigrate 中断,补一层列级自愈,避免 /api/db/persons 报 Unknown column。
ensurePersonSchema(db)
if err := db.AutoMigrate(&model.LinkTag{}); err != nil {
log.Printf("database: link_tags migrate warning: %v", err)
}
// 以下表业务大量使用,必须参与 AutoMigrate否则旧库缺字段会导致订单/用户/VIP 等接口报错
if err := db.AutoMigrate(&model.User{}); err != nil {
log.Printf("database: users migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.SystemConfig{}); err != nil {
log.Printf("database: system_config migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.Chapter{}); err != nil {
log.Printf("database: chapters migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.GiftPayRequest{}); err != nil {
log.Printf("database: gift_pay_requests migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.UserRule{}); err != nil {
log.Printf("database: user_rules migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.UserTrack{}); err != nil {
log.Printf("database: user_tracks migrate warning: %v", err)
}
if err := db.AutoMigrate(&model.UserRuleCompletion{}); err != nil {
log.Printf("database: user_rule_completions migrate warning: %v", err)
}
log.Println("database: connected")
return nil
}
// DB 返回全局 *gorm.DB仅在 Init 成功后调用
func DB() *gorm.DB {
return db
}
func ensurePersonSchema(db *gorm.DB) {
m := db.Migrator()
if !m.HasColumn(&model.Person{}, "is_pinned") {
if err := db.Exec("ALTER TABLE persons ADD COLUMN is_pinned TINYINT(1) NOT NULL DEFAULT 0 COMMENT '置顶到小程序首页'").Error; err != nil {
log.Printf("database: persons schema ensure warning: %v; action=add is_pinned", err)
}
}
if !m.HasColumn(&model.Person{}, "person_source") {
if err := db.Exec("ALTER TABLE persons ADD COLUMN person_source VARCHAR(32) NOT NULL DEFAULT '' COMMENT '来源:空=后台手工vip_sync=超级个体同步'").Error; err != nil {
log.Printf("database: persons schema ensure warning: %v; action=add person_source", err)
}
}
if !m.HasIndex(&model.Person{}, "idx_persons_is_pinned") {
if err := db.Exec("CREATE INDEX idx_persons_is_pinned ON persons(is_pinned)").Error; err != nil {
log.Printf("database: persons schema ensure warning: %v; action=create idx_persons_is_pinned", err)
}
}
}