Merge branch 'yongxu-dev' into devlop

# Conflicts:
#	.cursor/agent/软件测试/evolution/索引.md   resolved by yongxu-dev version
#	.cursor/skills/testing/SKILL.md   resolved by yongxu-dev version
#	.gitignore   resolved by yongxu-dev version
#	miniprogram/app.js   resolved by yongxu-dev version
#	miniprogram/app.json   resolved by yongxu-dev version
#	miniprogram/pages/chapters/chapters.js   resolved by yongxu-dev version
#	miniprogram/pages/index/index.js   resolved by yongxu-dev version
#	miniprogram/pages/index/index.wxml   resolved by yongxu-dev version
#	miniprogram/pages/match/match.js   resolved by yongxu-dev version
#	miniprogram/pages/my/my.js   resolved by yongxu-dev version
#	miniprogram/pages/my/my.wxml   resolved by yongxu-dev version
#	miniprogram/pages/my/my.wxss   resolved by yongxu-dev version
#	miniprogram/pages/read/read.js   resolved by yongxu-dev version
#	miniprogram/pages/read/read.wxml   resolved by yongxu-dev version
#	miniprogram/pages/read/read.wxss   resolved by yongxu-dev version
#	miniprogram/pages/wallet/wallet.js   resolved by yongxu-dev version
#	miniprogram/pages/wallet/wallet.wxml   resolved by yongxu-dev version
#	miniprogram/pages/wallet/wallet.wxss   resolved by yongxu-dev version
#	miniprogram/utils/ruleEngine.js   resolved by yongxu-dev version
#	miniprogram/utils/trackClick.js   resolved by yongxu-dev version
#	soul-admin/dist/index.html   resolved by yongxu-dev version
#	soul-admin/src/components/RichEditor.tsx   resolved by yongxu-dev version
#	soul-admin/src/layouts/AdminLayout.tsx   resolved by yongxu-dev version
#	soul-admin/src/pages/api-docs/ApiDocsPage.tsx   resolved by yongxu-dev version
#	soul-admin/src/pages/content/ContentPage.tsx   resolved by yongxu-dev version
#	soul-admin/src/pages/settings/SettingsPage.tsx   resolved by yongxu-dev version
#	soul-admin/tsconfig.tsbuildinfo   resolved by yongxu-dev version
#	soul-api/.env.production   resolved by yongxu-dev version
#	soul-api/internal/database/database.go   resolved by yongxu-dev version
#	soul-api/internal/handler/balance.go   resolved by yongxu-dev version
#	soul-api/internal/handler/book.go   resolved by yongxu-dev version
#	soul-api/internal/handler/ckb_open.go   resolved by yongxu-dev version
#	soul-api/internal/handler/db.go   resolved by yongxu-dev version
#	soul-api/internal/handler/db_book.go   resolved by yongxu-dev version
#	soul-api/internal/handler/db_person.go   resolved by yongxu-dev version
#	soul-api/internal/handler/search.go   resolved by yongxu-dev version
#	soul-api/internal/handler/upload.go   resolved by yongxu-dev version
#	soul-api/internal/router/router.go   resolved by yongxu-dev version
#	soul-api/wechat/info.log   resolved by yongxu-dev version
#	开发文档/10、项目管理/运营与变更.md   resolved by yongxu-dev version
#	开发文档/1、需求/需求汇总.md   resolved by yongxu-dev version
This commit is contained in:
Alex-larget
2026-03-17 14:23:26 +08:00
231 changed files with 14492 additions and 6576 deletions

View File

@@ -49,6 +49,12 @@ type Config struct {
// 订单对账定时任务间隔分钟0 表示不启动内置定时任务
SyncOrdersIntervalMinutes int
// 上传目录绝对路径air 运行时避免相对路径解析错误)
UploadDir string
// Redis 连接地址(如 redis://localhost:6379/0空表示不使用 Redis
RedisURL string
}
// BaseURLJoin 将路径拼接到 BaseURLpath 应以 / 开头
@@ -239,7 +245,18 @@ func Load() (*Config, error) {
}
}
return &Config{
// 上传目录:优先 UPLOAD_DIR 环境变量,否则用项目根下的 uploads
uploadDir := strings.TrimSpace(os.Getenv("UPLOAD_DIR"))
if uploadDir == "" {
uploadDir = resolveUploadDir(workDir, execDir)
} else if !filepath.IsAbs(uploadDir) {
uploadDir, _ = filepath.Abs(filepath.Join(workDir, uploadDir))
}
// RedisREDIS_URL 配置后启用;不配置则跳过。本地开发可设 REDIS_URL=redis://localhost:6379/0
redisURL := strings.TrimSpace(os.Getenv("REDIS_URL"))
cfg := &Config{
Port: port,
Mode: mode,
DBDSN: dsn,
@@ -265,5 +282,46 @@ func Load() (*Config, error) {
AdminPassword: adminPassword,
AdminSessionSecret: adminSessionSecret,
SyncOrdersIntervalMinutes: syncOrdersInterval,
}, nil
UploadDir: uploadDir,
RedisURL: redisURL,
}
// 生产环境GIN_MODE=release强制校验敏感配置禁止使用默认值
if cfg.Mode == "release" {
sensitive := []struct {
name string
val string
}{
{"WECHAT_APPSECRET", cfg.WechatAppSecret},
{"WECHAT_MCH_KEY", cfg.WechatMchKey},
{"WECHAT_APIV3_KEY", cfg.WechatAPIv3Key},
{"ADMIN_PASSWORD", cfg.AdminPassword},
{"ADMIN_SESSION_SECRET", cfg.AdminSessionSecret},
}
for _, s := range sensitive {
if s.val == "" ||
strings.HasPrefix(s.val, "wx3e31b068") ||
s.val == "admin123" ||
s.val == "soul-admin-secret-change-in-prod" {
log.Fatalf("生产环境必须配置 %s禁止使用默认值", s.name)
}
}
}
return cfg, nil
}
// resolveUploadDir 解析上传目录绝对路径air 运行时 exe 在 tmp/,需用项目根)
func resolveUploadDir(workDir, execDir string) string {
root := workDir
if execDir != "" {
base := filepath.Base(execDir)
if base == "tmp" {
root = filepath.Dir(execDir)
} else {
root = execDir
}
}
abs, _ := filepath.Abs(filepath.Join(root, "uploads"))
return abs
}