- 后端从 Python FastAPI 重写为 Go Gin(端口 56789) - 多班级完全隔离 - 超级管理员独立登录 - 课代表作业管理、排行榜分项排行 - 角色加减分上下限可配置 - 家长改密功能(可开关) - 周度/月度重置功能 - MySQL 5.7 兼容 - 43轮代码审查+全部修复 - Apache 2.0 许可证
164 lines
4.3 KiB
Go
164 lines
4.3 KiB
Go
// ===========================================
|
|
// 多班级版班级管理系统 - Go 后端
|
|
//
|
|
// 开发者: Canglan
|
|
// 联系方式: admin@sea-studio.top
|
|
// 版权归属: Sea Network Technology Studio
|
|
// 许可证: Apache License 2.0
|
|
//
|
|
// 版权所有 © Sea Network Technology Studio
|
|
// ===========================================
|
|
|
|
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/joho/godotenv"
|
|
)
|
|
|
|
// Config 应用全局配置结构体
|
|
type Config struct {
|
|
// 应用基础配置
|
|
AppName string
|
|
AppEnv string
|
|
Debug bool
|
|
AppPort string
|
|
|
|
// MySQL 数据库配置
|
|
DBHost string
|
|
DBPort int
|
|
DBUser string
|
|
DBPassword string
|
|
DBName string
|
|
DBMaxOpenConns int
|
|
DBMaxIdleConns int
|
|
DBConnMaxLife int // 秒
|
|
|
|
// Redis 配置
|
|
RedisHost string
|
|
RedisPort int
|
|
RedisPassword string
|
|
RedisDB int
|
|
RedisMaxConns int
|
|
|
|
// JWT 配置
|
|
JWTSecretKey string
|
|
JWTAlgorithm string
|
|
JWTExpireMinutes int
|
|
JWTIdleTimeoutMinutes int
|
|
|
|
// 密码加密(兼容 Python 版)
|
|
PasswordSalt string
|
|
|
|
// 系统管理员配置
|
|
SuperAdminLoginPath string
|
|
SuperAdminDefaultUser string
|
|
SuperAdminDefaultPass string
|
|
|
|
// 日志
|
|
LogLevel string
|
|
LogFile string
|
|
}
|
|
|
|
// AppConfig 全局配置实例
|
|
var AppConfig *Config
|
|
|
|
// Load 加载配置:先尝试加载 .env 文件,然后读取环境变量
|
|
func Load() (*Config, error) {
|
|
// 尝试加载 .env 文件(不存在不报错)
|
|
_ = godotenv.Load()
|
|
|
|
cfg := &Config{
|
|
AppName: getEnv("APP_NAME", "多班级版班级管理系统"),
|
|
AppEnv: getEnv("APP_ENV", "production"),
|
|
Debug: getEnvBool("DEBUG", false),
|
|
AppPort: getEnv("APP_PORT", "56789"),
|
|
|
|
DBHost: getEnv("DB_HOST", "localhost"),
|
|
DBPort: getEnvInt("DB_PORT", 3306),
|
|
DBUser: getEnv("DB_USER", "class_admin"),
|
|
DBPassword: getEnv("DB_PASSWORD", ""),
|
|
DBName: getEnv("DB_NAME", "classmanagerdb"),
|
|
DBMaxOpenConns: getEnvInt("DB_MAX_OPEN_CONNS", 25),
|
|
DBMaxIdleConns: getEnvInt("DB_MAX_IDLE_CONNS", 10),
|
|
DBConnMaxLife: getEnvInt("DB_CONN_MAX_LIFETIME", 300),
|
|
|
|
RedisHost: getEnv("REDIS_HOST", "localhost"),
|
|
RedisPort: getEnvInt("REDIS_PORT", 6379),
|
|
RedisPassword: getEnv("REDIS_PASSWORD", ""),
|
|
RedisDB: getEnvInt("REDIS_DB", 0),
|
|
RedisMaxConns: getEnvInt("REDIS_MAX_CONNECTIONS", 500),
|
|
|
|
JWTSecretKey: getEnv("JWT_SECRET_KEY", ""),
|
|
JWTAlgorithm: getEnv("JWT_ALGORITHM", "HS256"),
|
|
JWTExpireMinutes: getEnvInt("JWT_EXPIRE_MINUTES", 60),
|
|
JWTIdleTimeoutMinutes: getEnvInt("JWT_IDLE_TIMEOUT_MINUTES", 10),
|
|
|
|
PasswordSalt: getEnv("PASSWORD_SALT", ""),
|
|
|
|
SuperAdminLoginPath: getEnv("SUPER_ADMIN_LOGIN_PATH", "/super-admin"),
|
|
SuperAdminDefaultUser: getEnv("SUPER_ADMIN_DEFAULT_USERNAME", "admin"),
|
|
// 安全警告:默认密码仅用于首次部署初始化,上线前必须在 .env 中修改 SUPER_ADMIN_DEFAULT_PASSWORD。
|
|
// EnsureDefaultAdmin 通过 need_change_password=1 强制首次登录改密作为缓解措施。
|
|
SuperAdminDefaultPass: getEnv("SUPER_ADMIN_DEFAULT_PASSWORD", "Admin123"),
|
|
|
|
LogLevel: getEnv("LOG_LEVEL", "info"),
|
|
LogFile: getEnv("LOG_FILE", "logs/app.log"),
|
|
}
|
|
|
|
// 校验必填项
|
|
if cfg.JWTSecretKey == "" {
|
|
return nil, fmt.Errorf("配置 JWT_SECRET_KEY 不能为空")
|
|
}
|
|
if cfg.PasswordSalt == "" {
|
|
return nil, fmt.Errorf("配置 PASSWORD_SALT 不能为空")
|
|
}
|
|
|
|
AppConfig = cfg
|
|
return cfg, nil
|
|
}
|
|
|
|
// DSN 返回 MySQL 连接字符串
|
|
func (c *Config) DSN() string {
|
|
return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
|
|
c.DBUser, c.DBPassword, c.DBHost, c.DBPort, c.DBName)
|
|
}
|
|
|
|
// RedisAddr 返回 Redis 地址
|
|
func (c *Config) RedisAddr() string {
|
|
return fmt.Sprintf("%s:%d", c.RedisHost, c.RedisPort)
|
|
}
|
|
|
|
// IsProduction 判断是否为生产环境
|
|
func (c *Config) IsProduction() bool {
|
|
return c.AppEnv == "production"
|
|
}
|
|
|
|
// --- 辅助函数 ---
|
|
|
|
func getEnv(key, fallback string) string {
|
|
if val, ok := os.LookupEnv(key); ok {
|
|
return val
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
func getEnvInt(key string, fallback int) int {
|
|
if val, ok := os.LookupEnv(key); ok {
|
|
if i, err := strconv.Atoi(val); err == nil {
|
|
return i
|
|
}
|
|
}
|
|
return fallback
|
|
}
|
|
func getEnvBool(key string, fallback bool) bool {
|
|
if val, ok := os.LookupEnv(key); ok {
|
|
return strings.ToLower(val) == "true"
|
|
}
|
|
return fallback
|
|
}
|