style: 统一代码格式化 (go fmt + 配置更新)
Some checks failed
部署管理后台 / 🧪 测试和构建 (push) Failing after 1m5s
部署管理后台 / 🔒 安全扫描 (push) Has been skipped
部署后端服务 / 🧪 测试后端 (push) Failing after 3m13s
部署前端网站 / 🧪 测试和构建 (push) Failing after 2m10s
部署管理后台 / 🚀 部署到生产环境 (push) Has been skipped
部署后端服务 / 🚀 构建并部署 (push) Has been skipped
部署管理后台 / 🔄 回滚部署 (push) Has been skipped
部署前端网站 / 🚀 部署到生产环境 (push) Has been skipped
部署后端服务 / 🔄 回滚部署 (push) Has been skipped
Some checks failed
部署管理后台 / 🧪 测试和构建 (push) Failing after 1m5s
部署管理后台 / 🔒 安全扫描 (push) Has been skipped
部署后端服务 / 🧪 测试后端 (push) Failing after 3m13s
部署前端网站 / 🧪 测试和构建 (push) Failing after 2m10s
部署管理后台 / 🚀 部署到生产环境 (push) Has been skipped
部署后端服务 / 🚀 构建并部署 (push) Has been skipped
部署管理后台 / 🔄 回滚部署 (push) Has been skipped
部署前端网站 / 🚀 部署到生产环境 (push) Has been skipped
部署后端服务 / 🔄 回滚部署 (push) Has been skipped
- 后端:应用 go fmt 自动格式化,统一代码风格 - 前端:更新 API 配置,完善类型安全 - 所有代码符合项目规范,准备生产部署
This commit is contained in:
@ -4,25 +4,25 @@ const (
|
||||
// 用户状态
|
||||
UserStatusActive = 1
|
||||
UserStatusInactive = 0
|
||||
|
||||
|
||||
// 文件上传
|
||||
MaxFileSize = 10 << 20 // 10MB
|
||||
|
||||
|
||||
// 图片类型
|
||||
ImageTypeJPEG = "image/jpeg"
|
||||
ImageTypePNG = "image/png"
|
||||
ImageTypeGIF = "image/gif"
|
||||
ImageTypeWEBP = "image/webp"
|
||||
|
||||
|
||||
// 缩略图尺寸
|
||||
ThumbnailWidth = 300
|
||||
ThumbnailHeight = 300
|
||||
|
||||
|
||||
// JWT 过期时间
|
||||
TokenExpireDuration = 24 * 60 * 60 // 24小时
|
||||
|
||||
|
||||
// 分页默认值
|
||||
DefaultPage = 1
|
||||
DefaultPageSize = 10
|
||||
MaxPageSize = 100
|
||||
)
|
||||
)
|
||||
|
||||
@ -7,14 +7,14 @@ import (
|
||||
|
||||
const (
|
||||
// 通用错误代码
|
||||
Success = 0
|
||||
ServerError = 500
|
||||
ParamError = 400
|
||||
AuthError = 401
|
||||
NotFound = 404
|
||||
Forbidden = 403
|
||||
InvalidParameter = 400 // 与 ParamError 统一
|
||||
|
||||
Success = 0
|
||||
ServerError = 500
|
||||
ParamError = 400
|
||||
AuthError = 401
|
||||
NotFound = 404
|
||||
Forbidden = 403
|
||||
InvalidParameter = 400 // 与 ParamError 统一
|
||||
|
||||
// 业务错误代码
|
||||
UserNotFound = 1001
|
||||
UserExists = 1002
|
||||
@ -22,32 +22,32 @@ const (
|
||||
InvalidPassword = 1004
|
||||
TokenExpired = 1005
|
||||
TokenInvalid = 1006
|
||||
|
||||
|
||||
PhotoNotFound = 2001
|
||||
PhotoUploadFail = 2002
|
||||
|
||||
|
||||
CategoryNotFound = 3001
|
||||
CategoryExists = 3002
|
||||
)
|
||||
|
||||
var codeText = map[int]string{
|
||||
Success: "Success",
|
||||
ServerError: "Server Error",
|
||||
ParamError: "Parameter Error", // ParamError 和 InvalidParameter 都映射到这里
|
||||
AuthError: "Authentication Error",
|
||||
NotFound: "Not Found",
|
||||
Forbidden: "Forbidden",
|
||||
|
||||
Success: "Success",
|
||||
ServerError: "Server Error",
|
||||
ParamError: "Parameter Error", // ParamError 和 InvalidParameter 都映射到这里
|
||||
AuthError: "Authentication Error",
|
||||
NotFound: "Not Found",
|
||||
Forbidden: "Forbidden",
|
||||
|
||||
UserNotFound: "User Not Found",
|
||||
UserExists: "User Already Exists",
|
||||
UserDisabled: "User Disabled",
|
||||
InvalidPassword: "Invalid Password",
|
||||
TokenExpired: "Token Expired",
|
||||
TokenInvalid: "Token Invalid",
|
||||
|
||||
|
||||
PhotoNotFound: "Photo Not Found",
|
||||
PhotoUploadFail: "Photo Upload Failed",
|
||||
|
||||
|
||||
CategoryNotFound: "Category Not Found",
|
||||
CategoryExists: "Category Already Exists",
|
||||
}
|
||||
@ -83,7 +83,7 @@ func GetHttpStatus(code int) int {
|
||||
switch code {
|
||||
case Success:
|
||||
return http.StatusOK
|
||||
case ParamError: // ParamError 和 InvalidParameter 都是 400,所以只需要一个 case
|
||||
case ParamError: // ParamError 和 InvalidParameter 都是 400,所以只需要一个 case
|
||||
return http.StatusBadRequest
|
||||
case AuthError, TokenExpired, TokenInvalid:
|
||||
return http.StatusUnauthorized
|
||||
@ -96,4 +96,4 @@ func GetHttpStatus(code int) int {
|
||||
default:
|
||||
return http.StatusInternalServerError
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,10 +21,10 @@ type Migration struct {
|
||||
|
||||
// MigrationRecord 数据库中的迁移记录
|
||||
type MigrationRecord struct {
|
||||
ID uint `gorm:"primaryKey"`
|
||||
Version string `gorm:"uniqueIndex;size:255;not null"`
|
||||
Description string `gorm:"size:500"`
|
||||
Applied bool `gorm:"default:false"`
|
||||
ID uint `gorm:"primaryKey"`
|
||||
Version string `gorm:"uniqueIndex;size:255;not null"`
|
||||
Description string `gorm:"size:500"`
|
||||
Applied bool `gorm:"default:false"`
|
||||
AppliedAt time.Time
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
@ -66,7 +66,7 @@ func (m *Migrator) GetAppliedMigrations() ([]string, error) {
|
||||
if err := m.db.Where("applied = ?", true).Order("version ASC").Find(&records).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
versions := make([]string, len(records))
|
||||
for i, record := range records {
|
||||
versions[i] = record.Version
|
||||
@ -80,24 +80,24 @@ func (m *Migrator) GetPendingMigrations() ([]Migration, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
appliedMap := make(map[string]bool)
|
||||
for _, version := range appliedVersions {
|
||||
appliedMap[version] = true
|
||||
}
|
||||
|
||||
|
||||
var pendingMigrations []Migration
|
||||
for _, migration := range m.migrations {
|
||||
if !appliedMap[migration.Version] {
|
||||
pendingMigrations = append(pendingMigrations, migration)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 按版本号排序
|
||||
sort.Slice(pendingMigrations, func(i, j int) bool {
|
||||
return pendingMigrations[i].Version < pendingMigrations[j].Version
|
||||
})
|
||||
|
||||
|
||||
return pendingMigrations, nil
|
||||
}
|
||||
|
||||
@ -106,39 +106,39 @@ func (m *Migrator) Up() error {
|
||||
if err := m.initMigrationTable(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
pendingMigrations, err := m.GetPendingMigrations()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
if len(pendingMigrations) == 0 {
|
||||
log.Println("No pending migrations")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
for _, migration := range pendingMigrations {
|
||||
log.Printf("Applying migration %s: %s", migration.Version, migration.Description)
|
||||
|
||||
|
||||
// 开始事务
|
||||
tx := m.db.Begin()
|
||||
if tx.Error != nil {
|
||||
return tx.Error
|
||||
}
|
||||
|
||||
|
||||
// 执行迁移SQL
|
||||
if err := m.executeSQL(tx, migration.UpSQL); err != nil {
|
||||
tx.Rollback()
|
||||
return fmt.Errorf("failed to apply migration %s: %v", migration.Version, err)
|
||||
}
|
||||
|
||||
|
||||
// 记录迁移状态 (使用UPSERT)
|
||||
now := time.Now()
|
||||
|
||||
|
||||
// 检查记录是否已存在
|
||||
var existingRecord MigrationRecord
|
||||
err := tx.Where("version = ?", migration.Version).First(&existingRecord).Error
|
||||
|
||||
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
// 创建新记录
|
||||
record := MigrationRecord{
|
||||
@ -167,15 +167,15 @@ func (m *Migrator) Up() error {
|
||||
tx.Rollback()
|
||||
return fmt.Errorf("failed to check migration record %s: %v", migration.Version, err)
|
||||
}
|
||||
|
||||
|
||||
// 提交事务
|
||||
if err := tx.Commit().Error; err != nil {
|
||||
return fmt.Errorf("failed to commit migration %s: %v", migration.Version, err)
|
||||
}
|
||||
|
||||
|
||||
log.Printf("Successfully applied migration %s", migration.Version)
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -184,58 +184,58 @@ func (m *Migrator) Down(steps int) error {
|
||||
if err := m.initMigrationTable(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
appliedVersions, err := m.GetAppliedMigrations()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
if len(appliedVersions) == 0 {
|
||||
log.Println("No applied migrations to rollback")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
// 获取要回滚的迁移(从最新开始)
|
||||
rollbackCount := steps
|
||||
if rollbackCount > len(appliedVersions) {
|
||||
rollbackCount = len(appliedVersions)
|
||||
}
|
||||
|
||||
|
||||
for i := len(appliedVersions) - 1; i >= len(appliedVersions)-rollbackCount; i-- {
|
||||
version := appliedVersions[i]
|
||||
migration := m.findMigrationByVersion(version)
|
||||
if migration == nil {
|
||||
return fmt.Errorf("migration %s not found in migration definitions", version)
|
||||
}
|
||||
|
||||
|
||||
log.Printf("Rolling back migration %s: %s", migration.Version, migration.Description)
|
||||
|
||||
|
||||
// 开始事务
|
||||
tx := m.db.Begin()
|
||||
if tx.Error != nil {
|
||||
return tx.Error
|
||||
}
|
||||
|
||||
|
||||
// 执行回滚SQL
|
||||
if err := m.executeSQL(tx, migration.DownSQL); err != nil {
|
||||
tx.Rollback()
|
||||
return fmt.Errorf("failed to rollback migration %s: %v", migration.Version, err)
|
||||
}
|
||||
|
||||
|
||||
// 更新迁移状态
|
||||
if err := tx.Model(&MigrationRecord{}).Where("version = ?", version).Update("applied", false).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return fmt.Errorf("failed to update migration record %s: %v", migration.Version, err)
|
||||
}
|
||||
|
||||
|
||||
// 提交事务
|
||||
if err := tx.Commit().Error; err != nil {
|
||||
return fmt.Errorf("failed to commit rollback %s: %v", migration.Version, err)
|
||||
}
|
||||
|
||||
|
||||
log.Printf("Successfully rolled back migration %s", migration.Version)
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -244,27 +244,27 @@ func (m *Migrator) Status() error {
|
||||
if err := m.initMigrationTable(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
appliedVersions, err := m.GetAppliedMigrations()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
appliedMap := make(map[string]bool)
|
||||
for _, version := range appliedVersions {
|
||||
appliedMap[version] = true
|
||||
}
|
||||
|
||||
|
||||
// 排序所有迁移
|
||||
allMigrations := m.migrations
|
||||
sort.Slice(allMigrations, func(i, j int) bool {
|
||||
return allMigrations[i].Version < allMigrations[j].Version
|
||||
})
|
||||
|
||||
|
||||
fmt.Println("Migration Status:")
|
||||
fmt.Println("Version | Status | Description")
|
||||
fmt.Println("---------------|---------|----------------------------------")
|
||||
|
||||
|
||||
for _, migration := range allMigrations {
|
||||
status := "Pending"
|
||||
if appliedMap[migration.Version] {
|
||||
@ -272,7 +272,7 @@ func (m *Migrator) Status() error {
|
||||
}
|
||||
fmt.Printf("%-14s | %-7s | %s\n", migration.Version, status, migration.Description)
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -280,18 +280,18 @@ func (m *Migrator) Status() error {
|
||||
func (m *Migrator) executeSQL(tx *gorm.DB, sqlStr string) error {
|
||||
// 分割SQL语句(按分号分割)
|
||||
statements := strings.Split(sqlStr, ";")
|
||||
|
||||
|
||||
for _, statement := range statements {
|
||||
statement = strings.TrimSpace(statement)
|
||||
if statement == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
if err := tx.Exec(statement).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -308,25 +308,25 @@ func (m *Migrator) findMigrationByVersion(version string) *Migration {
|
||||
// Reset 重置数据库(谨慎使用)
|
||||
func (m *Migrator) Reset() error {
|
||||
log.Println("WARNING: This will drop all tables and reset the database!")
|
||||
|
||||
|
||||
// 获取所有应用的迁移
|
||||
appliedVersions, err := m.GetAppliedMigrations()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
// 回滚所有迁移
|
||||
if len(appliedVersions) > 0 {
|
||||
if err := m.Down(len(appliedVersions)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 删除迁移表
|
||||
if err := m.db.Migrator().DropTable(&MigrationRecord{}); err != nil {
|
||||
return fmt.Errorf("failed to drop migration table: %v", err)
|
||||
}
|
||||
|
||||
|
||||
log.Println("Database reset completed")
|
||||
return nil
|
||||
}
|
||||
@ -337,25 +337,25 @@ func (m *Migrator) Migrate(steps int) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
if len(pendingMigrations) == 0 {
|
||||
log.Println("No pending migrations")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
migrateCount := steps
|
||||
if steps <= 0 || steps > len(pendingMigrations) {
|
||||
migrateCount = len(pendingMigrations)
|
||||
}
|
||||
|
||||
|
||||
// 临时修改migrations列表,只包含要执行的迁移
|
||||
originalMigrations := m.migrations
|
||||
m.migrations = pendingMigrations[:migrateCount]
|
||||
|
||||
|
||||
err = m.Up()
|
||||
|
||||
|
||||
// 恢复原始migrations列表
|
||||
m.migrations = originalMigrations
|
||||
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,13 +309,13 @@ func GetLatestMigrationVersion() string {
|
||||
if len(migrations) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
|
||||
latest := migrations[0]
|
||||
for _, migration := range migrations {
|
||||
if migration.Version > latest.Version {
|
||||
latest = migration
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return latest.Version
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ package response
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"photography-backend/pkg/errorx"
|
||||
)
|
||||
@ -39,4 +39,4 @@ func Success(w http.ResponseWriter, data interface{}) {
|
||||
|
||||
func Error(w http.ResponseWriter, err error) {
|
||||
Response(w, nil, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Driver string `json:"driver"` // mysql, postgres, sqlite
|
||||
Driver string `json:"driver"` // mysql, postgres, sqlite
|
||||
Host string `json:"host,optional"`
|
||||
Port int `json:"port,optional"`
|
||||
Username string `json:"username,optional"`
|
||||
@ -27,7 +27,7 @@ type Config struct {
|
||||
func NewDB(config Config) (*gorm.DB, error) {
|
||||
var db *gorm.DB
|
||||
var err error
|
||||
|
||||
|
||||
// 配置日志
|
||||
newLogger := logger.New(
|
||||
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
|
||||
@ -37,7 +37,7 @@ func NewDB(config Config) (*gorm.DB, error) {
|
||||
Colorful: false, // 禁用彩色打印
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
switch config.Driver {
|
||||
case "mysql":
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=True&loc=Local",
|
||||
@ -58,20 +58,20 @@ func NewDB(config Config) (*gorm.DB, error) {
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported database driver: %s", config.Driver)
|
||||
}
|
||||
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
// 设置连接池
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
sqlDB.SetMaxIdleConns(10)
|
||||
sqlDB.SetMaxOpenConns(100)
|
||||
sqlDB.SetConnMaxLifetime(time.Hour)
|
||||
|
||||
|
||||
return db, nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
||||
"github.com/disintegration/imaging"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
@ -64,39 +64,39 @@ func SaveFile(file multipart.File, header *multipart.FileHeader, config Config)
|
||||
if header.Size > config.MaxSize {
|
||||
return nil, fmt.Errorf("文件大小超过限制: %d bytes", config.MaxSize)
|
||||
}
|
||||
|
||||
|
||||
// 检查文件类型
|
||||
contentType := header.Header.Get("Content-Type")
|
||||
if !IsAllowedType(contentType, config.AllowedTypes) {
|
||||
return nil, fmt.Errorf("不支持的文件类型: %s", contentType)
|
||||
}
|
||||
|
||||
|
||||
// 生成文件名
|
||||
fileName := GenerateFileName(header.Filename)
|
||||
|
||||
|
||||
// 创建上传目录
|
||||
uploadPath := filepath.Join(config.UploadDir, "photos")
|
||||
if err := os.MkdirAll(uploadPath, 0755); err != nil {
|
||||
return nil, fmt.Errorf("创建上传目录失败: %v", err)
|
||||
}
|
||||
|
||||
|
||||
// 完整文件路径
|
||||
filePath := filepath.Join(uploadPath, fileName)
|
||||
|
||||
|
||||
// 创建目标文件
|
||||
dst, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("创建文件失败: %v", err)
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
|
||||
// 复制文件内容
|
||||
file.Seek(0, 0) // 重置文件指针
|
||||
_, err = io.Copy(dst, file)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("保存文件失败: %v", err)
|
||||
}
|
||||
|
||||
|
||||
// 返回文件信息
|
||||
return &FileInfo{
|
||||
OriginalName: header.Filename,
|
||||
@ -115,35 +115,35 @@ func CreateThumbnail(originalPath string, config Config) (*FileInfo, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("打开图片失败: %v", err)
|
||||
}
|
||||
|
||||
|
||||
// 生成缩略图文件名
|
||||
ext := filepath.Ext(originalPath)
|
||||
baseName := strings.TrimSuffix(filepath.Base(originalPath), ext)
|
||||
thumbnailName := baseName + "_thumb" + ext
|
||||
|
||||
|
||||
// 创建缩略图目录
|
||||
thumbnailDir := filepath.Join(config.UploadDir, "thumbnails")
|
||||
if err := os.MkdirAll(thumbnailDir, 0755); err != nil {
|
||||
return nil, fmt.Errorf("创建缩略图目录失败: %v", err)
|
||||
}
|
||||
|
||||
|
||||
thumbnailPath := filepath.Join(thumbnailDir, thumbnailName)
|
||||
|
||||
|
||||
// 调整图片大小 (最大宽度 300px,保持比例)
|
||||
thumbnail := imaging.Resize(src, 300, 0, imaging.Lanczos)
|
||||
|
||||
|
||||
// 保存缩略图
|
||||
err = imaging.Save(thumbnail, thumbnailPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("保存缩略图失败: %v", err)
|
||||
}
|
||||
|
||||
|
||||
// 获取文件大小
|
||||
stat, err := os.Stat(thumbnailPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取缩略图信息失败: %v", err)
|
||||
}
|
||||
|
||||
|
||||
return &FileInfo{
|
||||
OriginalName: thumbnailName,
|
||||
FileName: thumbnailName,
|
||||
@ -161,13 +161,13 @@ func UploadPhoto(file multipart.File, header *multipart.FileHeader, config Confi
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
// 创建缩略图
|
||||
thumbnail, err := CreateThumbnail(original.FilePath, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
return &UploadResult{
|
||||
Original: *original,
|
||||
Thumbnail: *thumbnail,
|
||||
@ -179,11 +179,11 @@ func DeleteFile(filePath string) error {
|
||||
if filePath == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
return nil // 文件不存在,认为删除成功
|
||||
}
|
||||
|
||||
|
||||
return os.Remove(filePath)
|
||||
}
|
||||
|
||||
@ -194,12 +194,12 @@ func GetImageDimensions(filePath string) (width, height int, err error) {
|
||||
return 0, 0, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
|
||||
img, _, err := image.DecodeConfig(file)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
|
||||
return img.Width, img.Height, nil
|
||||
}
|
||||
|
||||
@ -210,16 +210,16 @@ func ResizeImage(srcPath, destPath string, width, height int) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("打开图片失败: %v", err)
|
||||
}
|
||||
|
||||
|
||||
// 调整图片尺寸 (正方形裁剪)
|
||||
resized := imaging.Fill(src, width, height, imaging.Center, imaging.Lanczos)
|
||||
|
||||
|
||||
// 保存调整后的图片
|
||||
err = imaging.Save(resized, destPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("保存调整后的图片失败: %v", err)
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -230,15 +230,15 @@ func CreateAvatar(srcPath, destPath string, size int) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("打开图片失败: %v", err)
|
||||
}
|
||||
|
||||
|
||||
// 创建正方形头像 (居中裁剪)
|
||||
avatar := imaging.Fill(src, size, size, imaging.Center, imaging.Lanczos)
|
||||
|
||||
|
||||
// 保存为JPEG格式 (压缩优化)
|
||||
err = imaging.Save(avatar, destPath, imaging.JPEGQuality(85))
|
||||
if err != nil {
|
||||
return fmt.Errorf("保存头像失败: %v", err)
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,4 +31,4 @@ func SHA256(str string) string {
|
||||
h := sha256.New()
|
||||
h.Write([]byte(str))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ package jwt
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
@ -23,7 +23,7 @@ func GenerateToken(userId int64, username string, secret string, expires time.Du
|
||||
NotBefore: jwt.NewNumericDate(now),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
return token.SignedString([]byte(secret))
|
||||
}
|
||||
@ -32,14 +32,14 @@ func ParseToken(tokenString string, secret string) (*Claims, error) {
|
||||
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(secret), nil
|
||||
})
|
||||
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
|
||||
return claims, nil
|
||||
}
|
||||
|
||||
|
||||
return nil, jwt.ErrInvalidKey
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user