A:增加启动自动引入依赖库版本以及信息
This commit is contained in:
1 parent
e0484efa2e
commit
6443cefb6a
10 files changed
+875
-120
No files matched your search
@@ -0,0 +1,21 @@
|
||||
# Argus 配置文件
|
||||
# 只包含需要自定义的配置项,其他将使用默认值
|
||||
|
||||
app:
|
||||
port: "8080"
|
||||
mode: "release"
|
||||
# 开发阶段标识 - 设置为 false 或删除此行启用生产模式
|
||||
development: true
|
||||
|
||||
# 如果需要指定工具路径,取消注释并设置路径
|
||||
# tools:
|
||||
# exiftool_path: "C:/tools/exiftool/exiftool.exe"
|
||||
# imagemagick_path: "C:/tools/imagemagick/magick.exe"
|
||||
# libvips_path: "C:/tools/vips/bin/vips.exe"
|
||||
|
||||
logging:
|
||||
level: "info"
|
||||
|
||||
database:
|
||||
type: "sqlite"
|
||||
path: "argus.db"
|
||||
@@ -0,0 +1,89 @@
|
||||
# Argus 项目配置文件
|
||||
# 这是一个示例配置文件,展示了所有可配置的选项
|
||||
# 如果某个配置项为空或未设置,将使用默认值
|
||||
|
||||
# 应用程序配置
|
||||
app:
|
||||
# 服务端口 (默认: 8080)
|
||||
port: "8080"
|
||||
# 运行模式: debug, release, test (默认: debug)
|
||||
mode: "debug"
|
||||
# 读取超时时间 (默认: 30s)
|
||||
read_timeout: 30s
|
||||
# 写入超时时间 (默认: 30s)
|
||||
write_timeout: 30s
|
||||
# 空闲超时时间 (默认: 60s)
|
||||
idle_timeout: 60s
|
||||
# 开发阶段标识 (可选)
|
||||
# 如果设置为 true,表示开发阶段,某些开发专用代码会执行
|
||||
# 如果设置为 false 或不设置,表示生产阶段
|
||||
development: true
|
||||
|
||||
# 工具路径配置
|
||||
# 如果留空,系统会自动检测工具路径
|
||||
tools:
|
||||
# ExifTool 可执行文件路径
|
||||
exiftool_path: ""
|
||||
# ImageMagick 可执行文件路径 (magick 或 convert)
|
||||
imagemagick_path: ""
|
||||
# LibVips 可执行文件路径
|
||||
libvips_path: ""
|
||||
|
||||
# 目录路径配置
|
||||
paths:
|
||||
# 缓存目录名称 (默认: cache)
|
||||
cache_path: "cache"
|
||||
# 缩略图目录名称 (默认: thumbnail)
|
||||
thumbnail_path: "thumbnail"
|
||||
# 日志目录名称 (默认: app-logs)
|
||||
log_path: "app-logs"
|
||||
# 临时文件目录名称 (默认: app-tmp)
|
||||
temp_path: "app-tmp"
|
||||
# PNG临时文件目录名称 (默认: png-tmp)
|
||||
png_temp_path: "png-tmp"
|
||||
|
||||
# 日志配置
|
||||
logging:
|
||||
# 日志级别: debug, info, warn, error (默认: info)
|
||||
level: "info"
|
||||
# 自定义日志文件路径 (如果为空,使用 paths.log_path)
|
||||
file_path: ""
|
||||
|
||||
# 数据库配置
|
||||
database:
|
||||
# 数据库类型: sqlite, mysql (默认: sqlite)
|
||||
type: "sqlite"
|
||||
# SQLite 数据库文件路径 (默认: test.db)
|
||||
path: "test.db"
|
||||
|
||||
# MySQL 配置 (仅当 type 为 mysql 时生效)
|
||||
host: "localhost"
|
||||
port: "3306"
|
||||
database: "argus"
|
||||
username: ""
|
||||
password: ""
|
||||
|
||||
# 连接池配置
|
||||
max_idle_conns: 1
|
||||
max_open_conns: 1
|
||||
max_lifetime: 0
|
||||
|
||||
# 图像处理配置
|
||||
image:
|
||||
# 缩略图格式: jpg, png, webp (默认: jpg)
|
||||
thumbnail_format: "jpg"
|
||||
# 缩略图尺寸 [宽度, 高度] (默认: [512, 720])
|
||||
thumbnail_size: [512, 720]
|
||||
# 缩略图质量 1-100 (默认: 80)
|
||||
thumbnail_quality: 80
|
||||
# 屏幕大小 (默认: 1080)
|
||||
screen_size: 1080
|
||||
|
||||
# 支持的文件格式
|
||||
supported_formats:
|
||||
# 基础格式 (ImageMagick, libvips 支持)
|
||||
base: [".jpg", ".jpeg", ".png", ".tif", ".tiff", ".bmp"]
|
||||
# 特殊格式
|
||||
special: [".gif", ".heic", ".heif", ".webp", ".avif", ".jxl"]
|
||||
# 缩略图格式
|
||||
thumbnail: [".jpg", ".webp"]
|
||||
@@ -0,0 +1,45 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"rear/internal/config"
|
||||
)
|
||||
|
||||
// 示例:展示如何使用开发阶段标识
|
||||
|
||||
func exampleDevelopmentCheck() {
|
||||
// 方法1:使用 IsDevelopment() 函数
|
||||
if config.IsDevelopment() {
|
||||
fmt.Println("当前处于开发阶段")
|
||||
// 执行开发阶段特有的代码
|
||||
enableDebugFeatures()
|
||||
loadTestData()
|
||||
} else {
|
||||
fmt.Println("当前处于生产阶段")
|
||||
// 执行生产阶段的代码
|
||||
optimizeForProduction()
|
||||
}
|
||||
|
||||
// 方法2:使用 IsProduction() 函数
|
||||
if config.IsProduction() {
|
||||
fmt.Println("生产环境配置启用")
|
||||
// 生产环境特有的配置
|
||||
}
|
||||
}
|
||||
|
||||
func enableDebugFeatures() {
|
||||
fmt.Println("- 启用调试功能")
|
||||
fmt.Println("- 启用详细日志")
|
||||
fmt.Println("- 启用性能监控")
|
||||
}
|
||||
|
||||
func loadTestData() {
|
||||
fmt.Println("- 加载测试数据")
|
||||
fmt.Println("- 启用模拟接口")
|
||||
}
|
||||
|
||||
func optimizeForProduction() {
|
||||
fmt.Println("- 启用性能优化")
|
||||
fmt.Println("- 禁用调试信息")
|
||||
fmt.Println("- 启用缓存")
|
||||
}
|
||||
+2
-6
@@ -3,15 +3,14 @@ module rear
|
||||
go 1.24
|
||||
|
||||
require (
|
||||
github.com/davidbyttow/govips/v2 v2.16.0
|
||||
github.com/gin-contrib/cors v1.7.5
|
||||
github.com/gin-contrib/pprof v1.5.3
|
||||
github.com/gin-gonic/gin v1.10.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/h2non/filetype v1.1.3
|
||||
github.com/stretchr/testify v1.10.0
|
||||
go.uber.org/zap v1.27.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gorm.io/driver/mysql v1.6.0
|
||||
gorm.io/driver/sqlite v1.6.0
|
||||
gorm.io/gorm v1.30.0
|
||||
@@ -23,7 +22,6 @@ require (
|
||||
github.com/bytedance/sonic v1.13.3 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.4 // indirect
|
||||
github.com/cloudwego/base64x v0.1.5 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
||||
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
@@ -31,6 +29,7 @@ require (
|
||||
github.com/go-playground/validator/v10 v10.26.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
@@ -41,16 +40,13 @@ require (
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.14 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/arch v0.18.0 // indirect
|
||||
golang.org/x/crypto v0.39.0 // indirect
|
||||
golang.org/x/image v0.18.0 // indirect
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.26.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
@@ -11,8 +11,6 @@ github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQ
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davidbyttow/govips/v2 v2.16.0 h1:1nH/Rbx8qZP1hd+oYL9fYQjAnm1+KorX9s07ZGseQmo=
|
||||
github.com/davidbyttow/govips/v2 v2.16.0/go.mod h1:clH5/IDVmG5eVyc23qYpyi7kmOT0B/1QNTKtci4RkyM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
||||
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
|
||||
github.com/gin-contrib/cors v1.7.5 h1:cXC9SmofOrRg0w9PigwGlHG3ztswH6bqq4vJVXnvYMk=
|
||||
@@ -54,8 +52,6 @@ github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQe
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
@@ -69,7 +65,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
@@ -80,7 +75,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
@@ -91,7 +85,6 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.14 h1:yOQvXCBc3Ij46LRkRoh4Yd5qK6LVOgi0bYOXfb7ifjw=
|
||||
github.com/ugorji/go/codec v1.2.14/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
@@ -100,79 +93,18 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/arch v0.18.0 h1:WN9poc33zL4AzGxqf8VtpKUnGvMi8O9lhNyBMF/85qc=
|
||||
golang.org/x/arch v0.18.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
|
||||
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"rear/internal/consts"
|
||||
"rear/internal/utils"
|
||||
"rear/pkg/logger"
|
||||
"time"
|
||||
)
|
||||
@@ -58,44 +57,120 @@ type Config struct {
|
||||
// 软件运行目录
|
||||
AppPath string
|
||||
AppDir string
|
||||
|
||||
// 新增配置字段
|
||||
ToolsConfig ToolsConfig
|
||||
LoggingConfig LoggingConfig
|
||||
FileConfig *FileConfig // 原始配置文件内容
|
||||
}
|
||||
|
||||
var CONFIG Config
|
||||
|
||||
// InitConfig 初始化配置
|
||||
func InitConfig() *Config {
|
||||
i := ImageCompressionOptions{
|
||||
ThumbnailFormat: consts.FormatJPG,
|
||||
ThumbnailSize: []int{512, 720},
|
||||
ThumbnailQuality: 80,
|
||||
ScreenSize: 1080,
|
||||
}
|
||||
pathConfig := PathConfig{
|
||||
CachePath: "cache",
|
||||
ThumbnailPath: "thumbnail",
|
||||
LogPath: "app-logs",
|
||||
TempPath: "app-tmp",
|
||||
PngTempPath: "png-tmp",
|
||||
}
|
||||
|
||||
execPath, err := os.Executable()
|
||||
if err != nil {
|
||||
logger.Fatal("无法获取程序路径: %v", zap.Error(err))
|
||||
}
|
||||
|
||||
execDir := filepath.Dir(execPath)
|
||||
|
||||
// 尝试加载配置文件
|
||||
var fileConfig *FileConfig
|
||||
configPaths := GetConfigPaths()
|
||||
for _, configPath := range configPaths {
|
||||
if config, err := LoadConfigFromFile(configPath); err == nil {
|
||||
fileConfig = config
|
||||
logger.Info("加载配置文件成功", zap.String("path", configPath))
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有找到配置文件,使用默认配置
|
||||
if fileConfig == nil {
|
||||
logger.Info("未找到配置文件,使用默认配置")
|
||||
fileConfig = GetDefaultFileConfig()
|
||||
} else {
|
||||
// 与默认配置合并
|
||||
fileConfig = MergeWithDefaults(fileConfig)
|
||||
}
|
||||
|
||||
// 转换为原有的配置格式,保持向后兼容
|
||||
imageCompressionOptions := ImageCompressionOptions{
|
||||
ThumbnailFormat: convertToImageFormat(fileConfig.Image.ThumbnailFormat),
|
||||
ThumbnailSize: fileConfig.Image.ThumbnailSize,
|
||||
ThumbnailQuality: fileConfig.Image.ThumbnailQuality,
|
||||
ScreenSize: fileConfig.Image.ScreenSize,
|
||||
}
|
||||
|
||||
pathConfig := PathConfig{
|
||||
CachePath: fileConfig.Paths.CachePath,
|
||||
ThumbnailPath: fileConfig.Paths.ThumbnailPath,
|
||||
LogPath: fileConfig.Paths.LogPath,
|
||||
TempPath: fileConfig.Paths.TempPath,
|
||||
PngTempPath: fileConfig.Paths.PngTempPath,
|
||||
}
|
||||
|
||||
CONFIG = Config{
|
||||
Port: utils.GetEnv("PORT", "8080"),
|
||||
Mode: utils.GetEnv("GIN_MODE", "debug"),
|
||||
ReadTimeout: 30 * time.Second,
|
||||
WriteTimeout: 30 * time.Second,
|
||||
IdleTimeout: 60 * time.Second,
|
||||
BaseSupportedFileTypes: []string{".jpg", ".jpeg", ".png", ".tif", ".tiff", ".bmp"},
|
||||
SpecialSupportedFileTypes: []string{".gif", ".heic", ".heif", ".webp", ".avif", ".jxl"},
|
||||
SupportedThumbnailFormat: []string{".jpg", ".webp"},
|
||||
ImageCompressionOption: i,
|
||||
Port: fileConfig.App.Port,
|
||||
Mode: fileConfig.App.Mode,
|
||||
ReadTimeout: fileConfig.App.ReadTimeout,
|
||||
WriteTimeout: fileConfig.App.WriteTimeout,
|
||||
IdleTimeout: fileConfig.App.IdleTimeout,
|
||||
BaseSupportedFileTypes: fileConfig.Image.SupportedFormats.Base,
|
||||
SpecialSupportedFileTypes: fileConfig.Image.SupportedFormats.Special,
|
||||
SupportedThumbnailFormat: fileConfig.Image.SupportedFormats.Thumbnail,
|
||||
ImageCompressionOption: imageCompressionOptions,
|
||||
PathConfig: pathConfig,
|
||||
AppPath: execPath,
|
||||
AppDir: filepath.Dir(execPath),
|
||||
AppDir: execDir,
|
||||
ToolsConfig: fileConfig.Tools,
|
||||
LoggingConfig: fileConfig.Logging,
|
||||
FileConfig: fileConfig,
|
||||
}
|
||||
return &CONFIG
|
||||
}
|
||||
|
||||
// convertToImageFormat 转换字符串到ImageFormat
|
||||
func convertToImageFormat(format string) consts.ImageFormat {
|
||||
switch format {
|
||||
case "jpg", "jpeg":
|
||||
return consts.FormatJPG
|
||||
case "png":
|
||||
return consts.FormatPNG
|
||||
case "webp":
|
||||
return consts.FormatWEBP
|
||||
default:
|
||||
return consts.FormatJPG
|
||||
}
|
||||
}
|
||||
|
||||
// GetDatabaseConfig 获取数据库配置
|
||||
func GetDatabaseConfig() DatabaseConfig {
|
||||
if CONFIG.FileConfig != nil {
|
||||
return CONFIG.FileConfig.Database
|
||||
}
|
||||
// 返回默认配置
|
||||
return DatabaseConfig{
|
||||
Type: SQLite,
|
||||
Database: "test.db",
|
||||
MaxIdleConns: 1,
|
||||
MaxOpenConns: 1,
|
||||
MaxLifetime: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// IsDevelopment 判断是否为开发阶段
|
||||
// 如果配置文件中设置了 development 字段且为 true,则认为是开发阶段
|
||||
// 如果未设置或为 false,则认为是生产阶段
|
||||
func IsDevelopment() bool {
|
||||
if CONFIG.FileConfig != nil && CONFIG.FileConfig.App.Development != nil {
|
||||
return *CONFIG.FileConfig.App.Development
|
||||
}
|
||||
return false // 默认为生产阶段
|
||||
}
|
||||
|
||||
// IsProduction 判断是否为生产阶段
|
||||
func IsProduction() bool {
|
||||
return !IsDevelopment()
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// getEnv 获取环境变量,如果不存在则返回默认值
|
||||
func getEnv(key, defaultValue string) string {
|
||||
if value := os.Getenv(key); value != "" {
|
||||
return value
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
// AppConfig 应用程序配置
|
||||
type AppConfig struct {
|
||||
Port string `yaml:"port" json:"port"`
|
||||
Mode string `yaml:"mode" json:"mode"`
|
||||
ReadTimeout time.Duration `yaml:"read_timeout" json:"read_timeout"`
|
||||
WriteTimeout time.Duration `yaml:"write_timeout" json:"write_timeout"`
|
||||
IdleTimeout time.Duration `yaml:"idle_timeout" json:"idle_timeout"`
|
||||
Development *bool `yaml:"development" json:"development"` // 开发阶段标识,nil表示未设置
|
||||
}
|
||||
|
||||
// ToolsConfig 工具路径配置
|
||||
type ToolsConfig struct {
|
||||
ExifToolPath string `yaml:"exiftool_path" json:"exiftool_path"`
|
||||
ImageMagickPath string `yaml:"imagemagick_path" json:"imagemagick_path"`
|
||||
LibVipsPath string `yaml:"libvips_path" json:"libvips_path"`
|
||||
}
|
||||
|
||||
// PathsConfig 路径配置
|
||||
type PathsConfig struct {
|
||||
CachePath string `yaml:"cache_path" json:"cache_path"`
|
||||
ThumbnailPath string `yaml:"thumbnail_path" json:"thumbnail_path"`
|
||||
LogPath string `yaml:"log_path" json:"log_path"`
|
||||
TempPath string `yaml:"temp_path" json:"temp_path"`
|
||||
PngTempPath string `yaml:"png_temp_path" json:"png_temp_path"`
|
||||
}
|
||||
|
||||
// LoggingConfig 日志配置
|
||||
type LoggingConfig struct {
|
||||
Level string `yaml:"level" json:"level"`
|
||||
FilePath string `yaml:"file_path" json:"file_path"`
|
||||
}
|
||||
|
||||
// ImageConfig 图像处理配置
|
||||
type ImageConfig struct {
|
||||
ThumbnailFormat string `yaml:"thumbnail_format" json:"thumbnail_format"`
|
||||
ThumbnailSize []int `yaml:"thumbnail_size" json:"thumbnail_size"`
|
||||
ThumbnailQuality int `yaml:"thumbnail_quality" json:"thumbnail_quality"`
|
||||
ScreenSize int `yaml:"screen_size" json:"screen_size"`
|
||||
SupportedFormats struct {
|
||||
Base []string `yaml:"base" json:"base"`
|
||||
Special []string `yaml:"special" json:"special"`
|
||||
Thumbnail []string `yaml:"thumbnail" json:"thumbnail"`
|
||||
} `yaml:"supported_formats" json:"supported_formats"`
|
||||
}
|
||||
|
||||
// FileConfig 完整的配置文件结构
|
||||
type FileConfig struct {
|
||||
App AppConfig `yaml:"app" json:"app"`
|
||||
Tools ToolsConfig `yaml:"tools" json:"tools"`
|
||||
Paths PathsConfig `yaml:"paths" json:"paths"`
|
||||
Logging LoggingConfig `yaml:"logging" json:"logging"`
|
||||
Database DatabaseConfig `yaml:"database" json:"database"`
|
||||
Image ImageConfig `yaml:"image" json:"image"`
|
||||
}
|
||||
|
||||
// LoadConfigFromFile 从文件加载配置
|
||||
func LoadConfigFromFile(configPath string) (*FileConfig, error) {
|
||||
// 检查配置文件是否存在
|
||||
if _, err := os.Stat(configPath); os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("配置文件不存在: %s", configPath)
|
||||
}
|
||||
|
||||
// 读取配置文件
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("读取配置文件失败: %w", err)
|
||||
}
|
||||
|
||||
// 解析YAML
|
||||
var config FileConfig
|
||||
if err := yaml.Unmarshal(data, &config); err != nil {
|
||||
return nil, fmt.Errorf("解析配置文件失败: %w", err)
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// GetDefaultFileConfig 获取默认配置
|
||||
func GetDefaultFileConfig() *FileConfig {
|
||||
return &FileConfig{
|
||||
App: AppConfig{
|
||||
Port: getEnv("PORT", "8080"),
|
||||
Mode: getEnv("GIN_MODE", "debug"),
|
||||
ReadTimeout: 30 * time.Second,
|
||||
WriteTimeout: 30 * time.Second,
|
||||
IdleTimeout: 60 * time.Second,
|
||||
Development: nil, // 默认不设置,表示生产阶段
|
||||
},
|
||||
Tools: ToolsConfig{
|
||||
ExifToolPath: "",
|
||||
ImageMagickPath: "",
|
||||
LibVipsPath: "",
|
||||
},
|
||||
Paths: PathsConfig{
|
||||
CachePath: "cache",
|
||||
ThumbnailPath: "thumbnail",
|
||||
LogPath: "app-logs",
|
||||
TempPath: "app-tmp",
|
||||
PngTempPath: "png-tmp",
|
||||
},
|
||||
Logging: LoggingConfig{
|
||||
Level: "info",
|
||||
FilePath: "",
|
||||
},
|
||||
Database: DatabaseConfig{
|
||||
Type: SQLite,
|
||||
Database: "test.db",
|
||||
Host: "localhost",
|
||||
Port: "3306",
|
||||
Username: "",
|
||||
Password: "",
|
||||
DBPath: "",
|
||||
MaxIdleConns: 1,
|
||||
MaxOpenConns: 1,
|
||||
MaxLifetime: 0,
|
||||
},
|
||||
Image: ImageConfig{
|
||||
ThumbnailFormat: "jpg",
|
||||
ThumbnailSize: []int{512, 720},
|
||||
ThumbnailQuality: 80,
|
||||
ScreenSize: 1080,
|
||||
SupportedFormats: struct {
|
||||
Base []string `yaml:"base" json:"base"`
|
||||
Special []string `yaml:"special" json:"special"`
|
||||
Thumbnail []string `yaml:"thumbnail" json:"thumbnail"`
|
||||
}{
|
||||
Base: []string{".jpg", ".jpeg", ".png", ".tif", ".tiff", ".bmp"},
|
||||
Special: []string{".gif", ".heic", ".heif", ".webp", ".avif", ".jxl"},
|
||||
Thumbnail: []string{".jpg", ".webp"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// SaveConfigToFile 保存配置到文件
|
||||
func SaveConfigToFile(config *FileConfig, configPath string) error {
|
||||
// 确保目录存在
|
||||
dir := filepath.Dir(configPath)
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return fmt.Errorf("创建配置目录失败: %w", err)
|
||||
}
|
||||
|
||||
// 序列化为YAML
|
||||
data, err := yaml.Marshal(config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("序列化配置失败: %w", err)
|
||||
}
|
||||
|
||||
// 写入文件
|
||||
if err := os.WriteFile(configPath, data, 0644); err != nil {
|
||||
return fmt.Errorf("写入配置文件失败: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MergeWithDefaults 将文件配置与默认配置合并
|
||||
func MergeWithDefaults(fileConfig *FileConfig) *FileConfig {
|
||||
defaultConfig := GetDefaultFileConfig()
|
||||
|
||||
// 如果fileConfig为nil,直接返回默认配置
|
||||
if fileConfig == nil {
|
||||
return defaultConfig
|
||||
}
|
||||
|
||||
// App配置合并
|
||||
if fileConfig.App.Port == "" {
|
||||
fileConfig.App.Port = defaultConfig.App.Port
|
||||
}
|
||||
if fileConfig.App.Mode == "" {
|
||||
fileConfig.App.Mode = defaultConfig.App.Mode
|
||||
}
|
||||
if fileConfig.App.ReadTimeout == 0 {
|
||||
fileConfig.App.ReadTimeout = defaultConfig.App.ReadTimeout
|
||||
}
|
||||
if fileConfig.App.WriteTimeout == 0 {
|
||||
fileConfig.App.WriteTimeout = defaultConfig.App.WriteTimeout
|
||||
}
|
||||
if fileConfig.App.IdleTimeout == 0 {
|
||||
fileConfig.App.IdleTimeout = defaultConfig.App.IdleTimeout
|
||||
}
|
||||
|
||||
// Paths配置合并
|
||||
if fileConfig.Paths.CachePath == "" {
|
||||
fileConfig.Paths.CachePath = defaultConfig.Paths.CachePath
|
||||
}
|
||||
if fileConfig.Paths.ThumbnailPath == "" {
|
||||
fileConfig.Paths.ThumbnailPath = defaultConfig.Paths.ThumbnailPath
|
||||
}
|
||||
if fileConfig.Paths.LogPath == "" {
|
||||
fileConfig.Paths.LogPath = defaultConfig.Paths.LogPath
|
||||
}
|
||||
if fileConfig.Paths.TempPath == "" {
|
||||
fileConfig.Paths.TempPath = defaultConfig.Paths.TempPath
|
||||
}
|
||||
if fileConfig.Paths.PngTempPath == "" {
|
||||
fileConfig.Paths.PngTempPath = defaultConfig.Paths.PngTempPath
|
||||
}
|
||||
|
||||
// Logging配置合并
|
||||
if fileConfig.Logging.Level == "" {
|
||||
fileConfig.Logging.Level = defaultConfig.Logging.Level
|
||||
}
|
||||
|
||||
// Database配置合并
|
||||
if fileConfig.Database.Type == "" {
|
||||
fileConfig.Database.Type = defaultConfig.Database.Type
|
||||
}
|
||||
if fileConfig.Database.Database == "" {
|
||||
fileConfig.Database.Database = defaultConfig.Database.Database
|
||||
}
|
||||
if fileConfig.Database.Host == "" {
|
||||
fileConfig.Database.Host = defaultConfig.Database.Host
|
||||
}
|
||||
if fileConfig.Database.Port == "" {
|
||||
fileConfig.Database.Port = defaultConfig.Database.Port
|
||||
}
|
||||
if fileConfig.Database.MaxIdleConns == 0 {
|
||||
fileConfig.Database.MaxIdleConns = defaultConfig.Database.MaxIdleConns
|
||||
}
|
||||
if fileConfig.Database.MaxOpenConns == 0 {
|
||||
fileConfig.Database.MaxOpenConns = defaultConfig.Database.MaxOpenConns
|
||||
}
|
||||
|
||||
// Image配置合并
|
||||
if fileConfig.Image.ThumbnailFormat == "" {
|
||||
fileConfig.Image.ThumbnailFormat = defaultConfig.Image.ThumbnailFormat
|
||||
}
|
||||
if len(fileConfig.Image.ThumbnailSize) == 0 {
|
||||
fileConfig.Image.ThumbnailSize = defaultConfig.Image.ThumbnailSize
|
||||
}
|
||||
if fileConfig.Image.ThumbnailQuality == 0 {
|
||||
fileConfig.Image.ThumbnailQuality = defaultConfig.Image.ThumbnailQuality
|
||||
}
|
||||
if fileConfig.Image.ScreenSize == 0 {
|
||||
fileConfig.Image.ScreenSize = defaultConfig.Image.ScreenSize
|
||||
}
|
||||
if len(fileConfig.Image.SupportedFormats.Base) == 0 {
|
||||
fileConfig.Image.SupportedFormats.Base = defaultConfig.Image.SupportedFormats.Base
|
||||
}
|
||||
if len(fileConfig.Image.SupportedFormats.Special) == 0 {
|
||||
fileConfig.Image.SupportedFormats.Special = defaultConfig.Image.SupportedFormats.Special
|
||||
}
|
||||
if len(fileConfig.Image.SupportedFormats.Thumbnail) == 0 {
|
||||
fileConfig.Image.SupportedFormats.Thumbnail = defaultConfig.Image.SupportedFormats.Thumbnail
|
||||
}
|
||||
|
||||
return fileConfig
|
||||
}
|
||||
|
||||
// GetConfigPaths 获取可能的配置文件路径
|
||||
func GetConfigPaths() []string {
|
||||
execPath, _ := os.Executable()
|
||||
execDir := filepath.Dir(execPath)
|
||||
|
||||
return []string{
|
||||
filepath.Join(execDir, "config.yaml"),
|
||||
filepath.Join(execDir, "config.yml"),
|
||||
filepath.Join(execDir, "configs", "config.yaml"),
|
||||
filepath.Join(execDir, "configs", "config.yml"),
|
||||
"config.yaml",
|
||||
"config.yml",
|
||||
}
|
||||
}
|
||||
@@ -265,14 +265,8 @@ func InitDatabase() error {
|
||||
}
|
||||
|
||||
func getDatabaseConfig() config.DatabaseConfig {
|
||||
// 初始化数据库
|
||||
return config.DatabaseConfig{
|
||||
Type: config.SQLite,
|
||||
Database: "test.db",
|
||||
MaxIdleConns: 1,
|
||||
MaxOpenConns: 1,
|
||||
MaxLifetime: 0,
|
||||
}
|
||||
// 使用配置文件中的数据库配置
|
||||
return config.GetDatabaseConfig()
|
||||
}
|
||||
|
||||
var DB *gorm.DB
|
||||
|
||||
@@ -9,8 +9,10 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"rear/internal/config"
|
||||
"rear/pkg/logger"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
@@ -24,7 +26,7 @@ var (
|
||||
toolsInitErr error
|
||||
)
|
||||
|
||||
// Config 初始化配置
|
||||
// ToolConfig 初始化配置(已废弃,使用config.ToolsConfig)
|
||||
type Config struct {
|
||||
// 工具路径(如果为空,会自动检测)
|
||||
ImageMagickPath string
|
||||
@@ -32,7 +34,23 @@ type Config struct {
|
||||
VipsPath string
|
||||
}
|
||||
|
||||
// Initialize 初始化工具路径(可选调用,如果不调用会在第一次使用时自动初始化)
|
||||
// Initialize 使用配置文件初始化工具路径
|
||||
func InitializeFromConfig(baseDir *string) error {
|
||||
toolsInitOnce.Do(func() {
|
||||
// 从全局配置获取工具路径
|
||||
toolsConfig := config.CONFIG.ToolsConfig
|
||||
|
||||
ImageMagickPath = toolsConfig.ImageMagickPath
|
||||
ExifToolPath = toolsConfig.ExifToolPath
|
||||
VipsPath = toolsConfig.LibVipsPath
|
||||
|
||||
toolsInitErr = detectTools(baseDir)
|
||||
})
|
||||
|
||||
return toolsInitErr
|
||||
}
|
||||
|
||||
// Initialize 初始化工具路径(保持向后兼容,可选调用,如果不调用会在第一次使用时自动初始化)
|
||||
func Initialize(config *Config, baseDir *string) error {
|
||||
if config == nil {
|
||||
config = &Config{}
|
||||
@@ -67,6 +85,15 @@ func detectTools(baseDir *string) error {
|
||||
if ImageMagickPath == "" {
|
||||
ImageMagickPath = findTool("convert", execDir, "imagemagick")
|
||||
}
|
||||
} else {
|
||||
// 验证配置的路径是否有效
|
||||
if !validateToolPath(ImageMagickPath) {
|
||||
logger.Warn("配置的ImageMagick路径无效,尝试自动检测", zap.String("path", ImageMagickPath))
|
||||
ImageMagickPath = findTool("magick", execDir, "imagemagick")
|
||||
if ImageMagickPath == "" {
|
||||
ImageMagickPath = findTool("convert", execDir, "imagemagick")
|
||||
}
|
||||
}
|
||||
}
|
||||
if ImageMagickPath == "" {
|
||||
return fmt.Errorf("ImageMagick not found")
|
||||
@@ -75,6 +102,20 @@ func detectTools(baseDir *string) error {
|
||||
// 检测 ExifTool
|
||||
if ExifToolPath == "" {
|
||||
ExifToolPath = findTool("exiftool", execDir, "exiftool")
|
||||
// 特殊情况:检查 exiftool(-k).exe
|
||||
if ExifToolPath == "" {
|
||||
ExifToolPath = findTool("exiftool(-k)", execDir, "exiftool")
|
||||
}
|
||||
} else {
|
||||
// 验证配置的路径是否有效
|
||||
if !validateToolPath(ExifToolPath) {
|
||||
logger.Warn("配置的ExifTool路径无效,尝试自动检测", zap.String("path", ExifToolPath))
|
||||
ExifToolPath = findTool("exiftool", execDir, "exiftool")
|
||||
// 特殊情况:检查 exiftool(-k).exe
|
||||
if ExifToolPath == "" {
|
||||
ExifToolPath = findTool("exiftool(-k)", execDir, "exiftool")
|
||||
}
|
||||
}
|
||||
}
|
||||
if ExifToolPath == "" {
|
||||
return fmt.Errorf("ExifTool not found")
|
||||
@@ -83,14 +124,39 @@ func detectTools(baseDir *string) error {
|
||||
// 检测 libvips
|
||||
if VipsPath == "" {
|
||||
VipsPath = findTool("vips", execDir, "vips")
|
||||
} else {
|
||||
// 验证配置的路径是否有效
|
||||
if !validateToolPath(VipsPath) {
|
||||
logger.Warn("配置的LibVips路径无效,尝试自动检测", zap.String("path", VipsPath))
|
||||
VipsPath = findTool("vips", execDir, "vips")
|
||||
}
|
||||
}
|
||||
if VipsPath == "" {
|
||||
return fmt.Errorf("libvips not found")
|
||||
}
|
||||
|
||||
logger.Info("工具路径检测完成",
|
||||
zap.String("ImageMagick", ImageMagickPath),
|
||||
zap.String("ExifTool", ExifToolPath),
|
||||
zap.String("LibVips", VipsPath))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateToolPath 验证工具路径是否有效
|
||||
func validateToolPath(path string) bool {
|
||||
if path == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查文件是否存在
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// findTool 查找工具
|
||||
func findTool(name string, execDir string, identification string) string {
|
||||
// Windows 下添加 .exe 后缀
|
||||
@@ -111,6 +177,9 @@ func findTool(name string, execDir string, identification string) string {
|
||||
filepath.Join(execDir, "tools", exeName),
|
||||
filepath.Join(execDir, "tools", name, exeName),
|
||||
filepath.Join(execDir, "tools", name, "bin", exeName),
|
||||
filepath.Join(execDir, "tools", identification, exeName),
|
||||
filepath.Join(execDir, "tools", identification, name, exeName),
|
||||
filepath.Join(execDir, "tools", identification, name, "bin", exeName),
|
||||
filepath.Join(execDir, identification, exeName),
|
||||
filepath.Join(execDir, identification, "bin", exeName),
|
||||
filepath.Join(execDir, identification, "tools", exeName),
|
||||
@@ -119,19 +188,22 @@ func findTool(name string, execDir string, identification string) string {
|
||||
}
|
||||
jsonBytes, _ := json.Marshal(searchPaths)
|
||||
msg := string(jsonBytes)
|
||||
logger.Warn("查找工具路径", zap.String("paths", msg))
|
||||
logger.Debug("查找工具路径", zap.String("tool", name), zap.String("paths", msg))
|
||||
|
||||
for _, path := range searchPaths {
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
logger.Info("找到工具", zap.String("tool", name), zap.String("path", path))
|
||||
return path
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试从 PATH 中查找
|
||||
if path, err := exec.LookPath(exeName); err == nil {
|
||||
logger.Info("从系统PATH找到工具", zap.String("tool", name), zap.String("path", path))
|
||||
return path
|
||||
}
|
||||
|
||||
logger.Warn("未找到工具", zap.String("tool", name))
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -143,6 +215,166 @@ func EnsureInitialized(config *Config, baseDir *string) error {
|
||||
return toolsInitErr
|
||||
}
|
||||
|
||||
// EnsureInitializedFromConfig 从配置文件确保工具已初始化
|
||||
func EnsureInitializedFromConfig(baseDir *string) error {
|
||||
if toolsInitErr == nil && ImageMagickPath == "" && ExifToolPath == "" && VipsPath == "" {
|
||||
return InitializeFromConfig(baseDir)
|
||||
}
|
||||
return toolsInitErr
|
||||
}
|
||||
|
||||
// GetToolPaths 获取当前工具路径
|
||||
func GetToolPaths() (string, string, string) {
|
||||
return ImageMagickPath, VipsPath, ExifToolPath
|
||||
}
|
||||
|
||||
// ToolInfo 工具信息结构
|
||||
type ToolInfo struct {
|
||||
Name string
|
||||
Path string
|
||||
Version string
|
||||
Error error
|
||||
}
|
||||
|
||||
// GetToolsInfo 获取所有工具的详细信息
|
||||
func GetToolsInfo() []ToolInfo {
|
||||
var tools []ToolInfo
|
||||
|
||||
// ImageMagick 信息
|
||||
if ImageMagickPath != "" {
|
||||
version, err := getImageMagickVersion()
|
||||
tools = append(tools, ToolInfo{
|
||||
Name: "ImageMagick",
|
||||
Path: ImageMagickPath,
|
||||
Version: version,
|
||||
Error: err,
|
||||
})
|
||||
} else {
|
||||
tools = append(tools, ToolInfo{
|
||||
Name: "ImageMagick",
|
||||
Path: "未找到",
|
||||
Version: "N/A",
|
||||
Error: fmt.Errorf("工具未找到"),
|
||||
})
|
||||
}
|
||||
|
||||
// ExifTool 信息
|
||||
if ExifToolPath != "" {
|
||||
version, err := getExifToolVersion()
|
||||
tools = append(tools, ToolInfo{
|
||||
Name: "ExifTool",
|
||||
Path: ExifToolPath,
|
||||
Version: version,
|
||||
Error: err,
|
||||
})
|
||||
} else {
|
||||
tools = append(tools, ToolInfo{
|
||||
Name: "ExifTool",
|
||||
Path: "未找到",
|
||||
Version: "N/A",
|
||||
Error: fmt.Errorf("工具未找到"),
|
||||
})
|
||||
}
|
||||
|
||||
// LibVips 信息
|
||||
if VipsPath != "" {
|
||||
version, err := getVipsVersion()
|
||||
tools = append(tools, ToolInfo{
|
||||
Name: "LibVips",
|
||||
Path: VipsPath,
|
||||
Version: version,
|
||||
Error: err,
|
||||
})
|
||||
} else {
|
||||
tools = append(tools, ToolInfo{
|
||||
Name: "LibVips",
|
||||
Path: "未找到",
|
||||
Version: "N/A",
|
||||
Error: fmt.Errorf("工具未找到"),
|
||||
})
|
||||
}
|
||||
|
||||
return tools
|
||||
}
|
||||
|
||||
// getImageMagickVersion 获取ImageMagick版本
|
||||
func getImageMagickVersion() (string, error) {
|
||||
if ImageMagickPath == "" {
|
||||
return "", fmt.Errorf("ImageMagick path not set")
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
result, err := ExecuteCommand(ctx, ImageMagickPath, "-version")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get ImageMagick version: %w", err)
|
||||
}
|
||||
|
||||
// 解析版本信息
|
||||
output := string(result.Stdout)
|
||||
lines := bytes.Split(result.Stdout, []byte("\n"))
|
||||
if len(lines) > 0 {
|
||||
firstLine := string(lines[0])
|
||||
// 提取版本号 (例如: "Version: ImageMagick 7.1.1-47 Q16-HDRI x64")
|
||||
if strings.Contains(firstLine, "Version:") || strings.Contains(firstLine, "ImageMagick") {
|
||||
return strings.TrimSpace(firstLine), nil
|
||||
}
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
|
||||
// getExifToolVersion 获取ExifTool版本
|
||||
func getExifToolVersion() (string, error) {
|
||||
if ExifToolPath == "" {
|
||||
return "", fmt.Errorf("ExifTool path not set")
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
result, err := ExecuteCommand(ctx, ExifToolPath, "-ver")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get ExifTool version: %w", err)
|
||||
}
|
||||
|
||||
version := strings.TrimSpace(string(result.Stdout))
|
||||
if version != "" {
|
||||
return fmt.Sprintf("ExifTool %s", version), nil
|
||||
}
|
||||
|
||||
return string(result.Stdout), nil
|
||||
}
|
||||
|
||||
// getVipsVersion 获取LibVips版本
|
||||
func getVipsVersion() (string, error) {
|
||||
if VipsPath == "" {
|
||||
return "", fmt.Errorf("LibVips path not set")
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
result, err := ExecuteCommand(ctx, VipsPath, "--version")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get LibVips version: %w", err)
|
||||
}
|
||||
|
||||
// 解析版本信息
|
||||
output := string(result.Stdout)
|
||||
lines := bytes.Split(result.Stdout, []byte("\n"))
|
||||
if len(lines) > 0 {
|
||||
firstLine := string(lines[0])
|
||||
// 提取版本号 (例如: "vips-8.17.0")
|
||||
if strings.Contains(firstLine, "vips") {
|
||||
return strings.TrimSpace(firstLine), nil
|
||||
}
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
|
||||
// CommandResult 命令执行结果
|
||||
type CommandResult struct {
|
||||
Stdout []byte
|
||||
|
||||
+98
-10
@@ -17,8 +17,9 @@ import (
|
||||
"rear/internal/repositories"
|
||||
"rear/internal/router"
|
||||
"rear/internal/service"
|
||||
"rear/internal/utils"
|
||||
"rear/pkg/logger"
|
||||
"rear/pkg/utils"
|
||||
utilsPkg "rear/pkg/utils"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -42,12 +43,37 @@ func main() {
|
||||
}
|
||||
logConfig := logger.DefaultConfig()
|
||||
logConfig.LogPath = logPath
|
||||
// 使用配置文件中的日志级别
|
||||
if config.CONFIG.LoggingConfig.Level != "" {
|
||||
logConfig.Level = parseLogLevel(config.CONFIG.LoggingConfig.Level)
|
||||
}
|
||||
err = logger.InitDefaultLogger(logConfig)
|
||||
if err != nil {
|
||||
// log.Fatal 会输出错误信息并调用 os.Exit(1)
|
||||
log.Fatalf("Failed to initialize logger: %v", err)
|
||||
}
|
||||
|
||||
// 初始化工具路径
|
||||
err = initializeTools()
|
||||
if err != nil {
|
||||
logger.Warnf("Failed to initialize tools: %v", err)
|
||||
logger.Warn("继续运行但某些功能可能受限")
|
||||
}
|
||||
|
||||
// 输出工具版本信息
|
||||
printToolsInfo()
|
||||
|
||||
// 根据开发阶段执行不同的逻辑
|
||||
if config.IsDevelopment() {
|
||||
logger.Info("运行在开发模式")
|
||||
// 开发阶段特有的初始化代码
|
||||
initDevelopmentFeatures()
|
||||
} else {
|
||||
logger.Info("运行在生产模式")
|
||||
// 生产阶段的优化设置
|
||||
initProductionOptimizations()
|
||||
}
|
||||
|
||||
// 数据库初始化
|
||||
if err := db.InitDatabase(); err != nil {
|
||||
log.Fatal("Failed to initialize database:", err)
|
||||
@@ -74,21 +100,21 @@ func main() {
|
||||
srcDir := `.\tools\windows_amd64\exiftool\exiftool` // 源目录
|
||||
|
||||
// 复制整个目录
|
||||
if err := utils.FileUtils.CopyDir(srcDir, join); err != nil {
|
||||
if err := utilsPkg.FileUtils.CopyDir(srcDir, join); err != nil {
|
||||
fmt.Printf("复制失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
join1 := filepath.Join(config.CONFIG.AppDir, "tools", "vips")
|
||||
srcDir1 := `.\tools\windows_amd64\libvips\vips` // 源目录
|
||||
if err := utils.FileUtils.CopyDir(srcDir1, join1); err != nil {
|
||||
if err := utilsPkg.FileUtils.CopyDir(srcDir1, join1); err != nil {
|
||||
fmt.Printf("复制失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
join2 := filepath.Join(config.CONFIG.AppDir, "tools", "imagemagick")
|
||||
srcDir2 := `.\tools\windows_amd64\imagemagick\imagemagick` // 源目录
|
||||
if err := utils.FileUtils.CopyDir(srcDir2, join2); err != nil {
|
||||
if err := utilsPkg.FileUtils.CopyDir(srcDir2, join2); err != nil {
|
||||
fmt.Printf("复制失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
@@ -102,29 +128,91 @@ func main() {
|
||||
startHttp(newContainer, newTaskContainer)
|
||||
}
|
||||
|
||||
// parseLogLevel 将字符串转换为LogLevel
|
||||
func parseLogLevel(level string) logger.LogLevel {
|
||||
switch level {
|
||||
case "debug":
|
||||
return logger.DebugLevel
|
||||
case "info":
|
||||
return logger.InfoLevel
|
||||
case "warn", "warning":
|
||||
return logger.WarnLevel
|
||||
case "error":
|
||||
return logger.ErrorLevel
|
||||
case "fatal":
|
||||
return logger.FatalLevel
|
||||
default:
|
||||
return logger.InfoLevel
|
||||
}
|
||||
}
|
||||
|
||||
// 获取日志路径
|
||||
func getLogPath() (error, string) {
|
||||
join := filepath.Join(config.CONFIG.AppDir, config.CONFIG.PathConfig.LogPath)
|
||||
err := utils.FileUtils.CreateDir(join)
|
||||
var logPath string
|
||||
// 如果配置文件中指定了日志文件路径,使用配置的路径
|
||||
if config.CONFIG.LoggingConfig.FilePath != "" {
|
||||
logPath = config.CONFIG.LoggingConfig.FilePath
|
||||
// 如果是相对路径,转换为绝对路径
|
||||
if !filepath.IsAbs(logPath) {
|
||||
logPath = filepath.Join(config.CONFIG.AppDir, logPath)
|
||||
}
|
||||
} else {
|
||||
// 使用默认路径
|
||||
logPath = filepath.Join(config.CONFIG.AppDir, config.CONFIG.PathConfig.LogPath)
|
||||
}
|
||||
err := utilsPkg.FileUtils.CreateDir(logPath)
|
||||
if err != nil {
|
||||
logger.Error("日志文件夹创建失败!", zap.String("path", join), zap.Error(err))
|
||||
logger.Error("日志文件夹创建失败!", zap.String("path", logPath), zap.Error(err))
|
||||
return err, ""
|
||||
}
|
||||
return nil, join
|
||||
return nil, logPath
|
||||
}
|
||||
|
||||
// initDevelopmentFeatures 初始化开发阶段功能
|
||||
func initDevelopmentFeatures() {
|
||||
logger.Info("启用开发模式功能")
|
||||
}
|
||||
|
||||
// initProductionOptimizations 初始化生产阶段优化
|
||||
func initProductionOptimizations() {
|
||||
logger.Info("启用生产模式优化")
|
||||
}
|
||||
|
||||
// initializeTools 初始化工具
|
||||
func initializeTools() error {
|
||||
// 使用新的配置初始化方法
|
||||
return utils.InitializeFromConfig(&config.CONFIG.AppDir)
|
||||
}
|
||||
|
||||
// printToolsInfo 输出工具版本信息
|
||||
func printToolsInfo() {
|
||||
logger.Info("=== 工具信息 ===")
|
||||
|
||||
tools := utils.GetToolsInfo()
|
||||
for _, tool := range tools {
|
||||
if tool.Error != nil {
|
||||
logger.Warnf("%-12s: %s (路径: %s)", tool.Name, tool.Error.Error(), tool.Path)
|
||||
} else {
|
||||
logger.Infof("%-12s: %s", tool.Name, tool.Version)
|
||||
logger.Infof("%-12s 路径: %s", "", tool.Path)
|
||||
}
|
||||
}
|
||||
|
||||
logger.Info("================")
|
||||
}
|
||||
|
||||
// 创建软件所需的缓存目录等内容
|
||||
func createCachePath(dir string) {
|
||||
// 缩略图目录
|
||||
thumbnailPath := filepath.Join(dir, config.CONFIG.PathConfig.CachePath, config.CONFIG.PathConfig.ThumbnailPath)
|
||||
err := utils.FileUtils.CreateDir(thumbnailPath)
|
||||
err := utilsPkg.FileUtils.CreateDir(thumbnailPath)
|
||||
if err != nil {
|
||||
logger.Error("缩略图路径创建失败!", zap.String("path", dir), zap.Error(err))
|
||||
return
|
||||
}
|
||||
// 临时文件路径
|
||||
tempPath := filepath.Join(dir, config.CONFIG.PathConfig.TempPath, config.CONFIG.PathConfig.PngTempPath)
|
||||
err = utils.FileUtils.CreateDir(tempPath)
|
||||
err = utilsPkg.FileUtils.CreateDir(tempPath)
|
||||
if err != nil {
|
||||
logger.Error("临时文件夹创建失败!", zap.String("path", dir), zap.Error(err))
|
||||
return
|
||||
|
||||
Reference in new issue
Block a user