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

- 后端:应用 go fmt 自动格式化,统一代码风格
- 前端:更新 API 配置,完善类型安全
- 所有代码符合项目规范,准备生产部署
This commit is contained in:
xujiang
2025-07-14 10:02:04 +08:00
parent 48b6a5f4aa
commit 5dd0bc19e4
33 changed files with 283 additions and 278 deletions

View File

@ -29,8 +29,8 @@ func main() {
// 添加静态文件服务 // 添加静态文件服务
server.AddRoute(rest.Route{ server.AddRoute(rest.Route{
Method: http.MethodGet, Method: http.MethodGet,
Path: "/uploads/*", Path: "/uploads/*",
Handler: func(w http.ResponseWriter, r *http.Request) { Handler: func(w http.ResponseWriter, r *http.Request) {
http.StripPrefix("/uploads/", http.FileServer(http.Dir("uploads"))).ServeHTTP(w, r) http.StripPrefix("/uploads/", http.FileServer(http.Dir("uploads"))).ServeHTTP(w, r)
}, },

View File

@ -7,8 +7,8 @@ import (
type Config struct { type Config struct {
rest.RestConf rest.RestConf
Database database.Config `json:"database"` Database database.Config `json:"database"`
Auth AuthConfig `json:"auth"` Auth AuthConfig `json:"auth"`
FileUpload FileUploadConfig `json:"file_upload"` FileUpload FileUploadConfig `json:"file_upload"`
Middleware MiddlewareConfig `json:"middleware"` Middleware MiddlewareConfig `json:"middleware"`
} }
@ -28,6 +28,6 @@ type MiddlewareConfig struct {
EnableCORS bool `json:"enable_cors"` EnableCORS bool `json:"enable_cors"`
EnableLogger bool `json:"enable_logger"` EnableLogger bool `json:"enable_logger"`
EnableErrorHandle bool `json:"enable_error_handle"` EnableErrorHandle bool `json:"enable_error_handle"`
CORSOrigins []string `json:"cors_origins"` CORSOrigins []string `json:"cors_origins"`
LogLevel string `json:"log_level"` LogLevel string `json:"log_level"`
} }

View File

@ -49,10 +49,10 @@ func (l *RegisterLogic) Register(req *types.RegisterRequest) (resp *types.Regist
// 4. 创建用户 // 4. 创建用户
user := &model.User{ user := &model.User{
Username: req.Username, Username: req.Username,
Email: req.Email, Email: req.Email,
Password: hashedPassword, Password: hashedPassword,
Status: 1, // 默认激活状态 Status: 1, // 默认激活状态
CreatedAt: time.Now(), CreatedAt: time.Now(),
UpdatedAt: time.Now(), UpdatedAt: time.Now(),
} }

View File

@ -55,7 +55,7 @@ func (l *UploadAvatarLogic) UploadAvatar(req *types.UploadAvatarRequest, r *http
// 4. 获取上传的文件 // 4. 获取上传的文件
uploadedFile, header, err := r.FormFile("avatar") uploadedFile, header, err := r.FormFile("avatar")
if err != nil { if err != nil {
return nil, errorx.New(errorx.ParamError, "获取上传文件失败: " + err.Error()) return nil, errorx.New(errorx.ParamError, "获取上传文件失败: "+err.Error())
} }
defer uploadedFile.Close() defer uploadedFile.Close()
@ -93,7 +93,7 @@ func (l *UploadAvatarLogic) UploadAvatar(req *types.UploadAvatarRequest, r *http
// 8. 确保头像目录存在 // 8. 确保头像目录存在
if err := os.MkdirAll(avatarDir, 0755); err != nil { if err := os.MkdirAll(avatarDir, 0755); err != nil {
return nil, errorx.New(errorx.ServerError, "创建头像目录失败: " + err.Error()) return nil, errorx.New(errorx.ServerError, "创建头像目录失败: "+err.Error())
} }
avatarPath := filepath.Join(avatarDir, filename) avatarPath := filepath.Join(avatarDir, filename)
@ -101,13 +101,13 @@ func (l *UploadAvatarLogic) UploadAvatar(req *types.UploadAvatarRequest, r *http
// 9. 保存原始头像文件 // 9. 保存原始头像文件
destFile, err := os.Create(avatarPath) destFile, err := os.Create(avatarPath)
if err != nil { if err != nil {
return nil, errorx.New(errorx.ServerError, "创建头像文件失败: " + err.Error()) return nil, errorx.New(errorx.ServerError, "创建头像文件失败: "+err.Error())
} }
defer destFile.Close() defer destFile.Close()
_, err = io.Copy(destFile, uploadedFile) _, err = io.Copy(destFile, uploadedFile)
if err != nil { if err != nil {
return nil, errorx.New(errorx.ServerError, "保存头像文件失败: " + err.Error()) return nil, errorx.New(errorx.ServerError, "保存头像文件失败: "+err.Error())
} }
// 10. 生成压缩版本的头像 (150x150像素) // 10. 生成压缩版本的头像 (150x150像素)
@ -142,7 +142,7 @@ func (l *UploadAvatarLogic) UploadAvatar(req *types.UploadAvatarRequest, r *http
if avatarPath != compressedPath { if avatarPath != compressedPath {
os.Remove(compressedPath) os.Remove(compressedPath)
} }
return nil, errorx.New(errorx.ServerError, "更新用户头像失败: " + err.Error()) return nil, errorx.New(errorx.ServerError, "更新用户头像失败: "+err.Error())
} }
return &types.UploadAvatarResponse{ return &types.UploadAvatarResponse{

View File

@ -19,8 +19,8 @@ type ErrorConfig struct {
EnableDetailedErrors bool // 是否启用详细错误信息 (开发环境) EnableDetailedErrors bool // 是否启用详细错误信息 (开发环境)
EnableStackTrace bool // 是否启用堆栈跟踪 EnableStackTrace bool // 是否启用堆栈跟踪
EnableErrorMonitor bool // 是否启用错误监控 EnableErrorMonitor bool // 是否启用错误监控
IgnoreHTTPCodes []int // 忽略的HTTP状态码 (不记录为错误) IgnoreHTTPCodes []int // 忽略的HTTP状态码 (不记录为错误)
SensitiveFields []string // 敏感字段列表 (日志时隐藏) SensitiveFields []string // 敏感字段列表 (日志时隐藏)
} }
// DefaultErrorConfig 默认错误配置 // DefaultErrorConfig 默认错误配置
@ -29,8 +29,8 @@ func DefaultErrorConfig() ErrorConfig {
EnableDetailedErrors: false, // 生产环境默认关闭 EnableDetailedErrors: false, // 生产环境默认关闭
EnableStackTrace: false, // 生产环境默认关闭 EnableStackTrace: false, // 生产环境默认关闭
EnableErrorMonitor: true, EnableErrorMonitor: true,
IgnoreHTTPCodes: []int{http.StatusNotFound, http.StatusMethodNotAllowed}, IgnoreHTTPCodes: []int{http.StatusNotFound, http.StatusMethodNotAllowed},
SensitiveFields: []string{"password", "token", "secret", "key", "authorization"}, SensitiveFields: []string{"password", "token", "secret", "key", "authorization"},
} }
} }

View File

@ -15,8 +15,8 @@ import (
// LoggerConfig 日志配置 // LoggerConfig 日志配置
type LoggerConfig struct { type LoggerConfig struct {
EnableRequestBody bool // 是否记录请求体 EnableRequestBody bool // 是否记录请求体
EnableResponseBody bool // 是否记录响应体 EnableResponseBody bool // 是否记录响应体
MaxBodySize int64 // 最大记录的请求/响应体大小 MaxBodySize int64 // 最大记录的请求/响应体大小
SkipPaths []string // 跳过记录的路径 SkipPaths []string // 跳过记录的路径
SlowRequestDuration time.Duration // 慢请求阈值 SlowRequestDuration time.Duration // 慢请求阈值
@ -26,9 +26,9 @@ type LoggerConfig struct {
// DefaultLoggerConfig 默认日志配置 // DefaultLoggerConfig 默认日志配置
func DefaultLoggerConfig() LoggerConfig { func DefaultLoggerConfig() LoggerConfig {
return LoggerConfig{ return LoggerConfig{
EnableRequestBody: false, // 默认不记录请求体 (可能包含敏感信息) EnableRequestBody: false, // 默认不记录请求体 (可能包含敏感信息)
EnableResponseBody: false, // 默认不记录响应体 (减少日志量) EnableResponseBody: false, // 默认不记录响应体 (减少日志量)
MaxBodySize: 1024, // 最大记录1KB MaxBodySize: 1024, // 最大记录1KB
SkipPaths: []string{"/health", "/metrics", "/favicon.ico"}, SkipPaths: []string{"/health", "/metrics", "/favicon.ico"},
SlowRequestDuration: 1 * time.Second, SlowRequestDuration: 1 * time.Second,
EnablePanicRecover: true, EnablePanicRecover: true,
@ -60,7 +60,7 @@ func newResponseWriter(w http.ResponseWriter) *responseWriter {
return &responseWriter{ return &responseWriter{
ResponseWriter: w, ResponseWriter: w,
status: http.StatusOK, status: http.StatusOK,
body: &bytes.Buffer{}, body: &bytes.Buffer{},
} }
} }
@ -208,13 +208,13 @@ func (m *LoggerMiddleware) logRequestStart(r *http.Request, requestID, requestBo
// logRequestComplete 记录请求完成 // logRequestComplete 记录请求完成
func (m *LoggerMiddleware) logRequestComplete(r *http.Request, requestID string, status int, size int64, duration time.Duration, responseBody string) { func (m *LoggerMiddleware) logRequestComplete(r *http.Request, requestID string, status int, size int64, duration time.Duration, responseBody string) {
fields := map[string]interface{}{ fields := map[string]interface{}{
"request_id": requestID, "request_id": requestID,
"method": r.Method, "method": r.Method,
"path": r.URL.Path, "path": r.URL.Path,
"status": status, "status": status,
"response_size": size, "response_size": size,
"duration_ms": duration.Milliseconds(), "duration_ms": duration.Milliseconds(),
"duration": duration.String(), "duration": duration.String(),
} }
if responseBody != "" { if responseBody != "" {

View File

@ -13,11 +13,11 @@ import (
// MiddlewareManager 中间件管理器 // MiddlewareManager 中间件管理器
type MiddlewareManager struct { type MiddlewareManager struct {
config config.Config config config.Config
corsMiddleware *CORSMiddleware corsMiddleware *CORSMiddleware
logMiddleware *LoggerMiddleware logMiddleware *LoggerMiddleware
errorMiddleware *ErrorMiddleware errorMiddleware *ErrorMiddleware
authMiddleware *AuthMiddleware authMiddleware *AuthMiddleware
} }
// NewMiddlewareManager 创建中间件管理器 // NewMiddlewareManager 创建中间件管理器
@ -108,9 +108,9 @@ func (m *MiddlewareManager) Chain(handler http.HandlerFunc, middlewares ...func(
// GetGlobalMiddlewares 获取全局中间件 // GetGlobalMiddlewares 获取全局中间件
func (m *MiddlewareManager) GetGlobalMiddlewares() []func(http.HandlerFunc) http.HandlerFunc { func (m *MiddlewareManager) GetGlobalMiddlewares() []func(http.HandlerFunc) http.HandlerFunc {
return []func(http.HandlerFunc) http.HandlerFunc{ return []func(http.HandlerFunc) http.HandlerFunc{
m.errorMiddleware.Handle, // 错误处理 (最外层) m.errorMiddleware.Handle, // 错误处理 (最外层)
m.corsMiddleware.Handle, // CORS 处理 m.corsMiddleware.Handle, // CORS 处理
m.logMiddleware.Handle, // 日志记录 m.logMiddleware.Handle, // 日志记录
} }
} }

View File

@ -3,8 +3,8 @@ package model
import ( import (
"context" "context"
"fmt" "fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/sqlx" "github.com/zeromicro/go-zero/core/stores/sqlx"
"strings"
) )
var _ CategoryModel = (*customCategoryModel)(nil) var _ CategoryModel = (*customCategoryModel)(nil)

View File

@ -3,8 +3,8 @@ package model
import ( import (
"context" "context"
"fmt" "fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/sqlx" "github.com/zeromicro/go-zero/core/stores/sqlx"
"strings"
) )
var _ PhotoModel = (*customPhotoModel)(nil) var _ PhotoModel = (*customPhotoModel)(nil)

View File

@ -3,8 +3,8 @@ package model
import ( import (
"context" "context"
"fmt" "fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/sqlx" "github.com/zeromicro/go-zero/core/stores/sqlx"
"strings"
) )
var _ UserModel = (*customUserModel)(nil) var _ UserModel = (*customUserModel)(nil)

View File

@ -2,17 +2,17 @@ package svc
import ( import (
"fmt" "fmt"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"gorm.io/gorm" "gorm.io/gorm"
"photography-backend/internal/config" "photography-backend/internal/config"
"photography-backend/internal/middleware" "photography-backend/internal/middleware"
"photography-backend/internal/model" "photography-backend/internal/model"
"photography-backend/pkg/utils/database" "photography-backend/pkg/utils/database"
"github.com/zeromicro/go-zero/core/stores/sqlx"
) )
type ServiceContext struct { type ServiceContext struct {
Config config.Config Config config.Config
DB *gorm.DB DB *gorm.DB
UserModel model.UserModel UserModel model.UserModel
PhotoModel model.PhotoModel PhotoModel model.PhotoModel
CategoryModel model.CategoryModel CategoryModel model.CategoryModel
@ -29,8 +29,8 @@ func NewServiceContext(c config.Config) *ServiceContext {
sqlxConn := sqlx.NewSqlConn(getSQLDriverName(c.Database.Driver), getSQLDataSource(c.Database)) sqlxConn := sqlx.NewSqlConn(getSQLDriverName(c.Database.Driver), getSQLDataSource(c.Database))
return &ServiceContext{ return &ServiceContext{
Config: c, Config: c,
DB: db, DB: db,
UserModel: model.NewUserModel(sqlxConn), UserModel: model.NewUserModel(sqlxConn),
PhotoModel: model.NewPhotoModel(sqlxConn), PhotoModel: model.NewPhotoModel(sqlxConn),
CategoryModel: model.NewCategoryModel(sqlxConn), CategoryModel: model.NewCategoryModel(sqlxConn),

View File

@ -7,13 +7,13 @@ import (
const ( const (
// 通用错误代码 // 通用错误代码
Success = 0 Success = 0
ServerError = 500 ServerError = 500
ParamError = 400 ParamError = 400
AuthError = 401 AuthError = 401
NotFound = 404 NotFound = 404
Forbidden = 403 Forbidden = 403
InvalidParameter = 400 // 与 ParamError 统一 InvalidParameter = 400 // 与 ParamError 统一
// 业务错误代码 // 业务错误代码
UserNotFound = 1001 UserNotFound = 1001
@ -31,12 +31,12 @@ const (
) )
var codeText = map[int]string{ var codeText = map[int]string{
Success: "Success", Success: "Success",
ServerError: "Server Error", ServerError: "Server Error",
ParamError: "Parameter Error", // ParamError 和 InvalidParameter 都映射到这里 ParamError: "Parameter Error", // ParamError 和 InvalidParameter 都映射到这里
AuthError: "Authentication Error", AuthError: "Authentication Error",
NotFound: "Not Found", NotFound: "Not Found",
Forbidden: "Forbidden", Forbidden: "Forbidden",
UserNotFound: "User Not Found", UserNotFound: "User Not Found",
UserExists: "User Already Exists", UserExists: "User Already Exists",
@ -83,7 +83,7 @@ func GetHttpStatus(code int) int {
switch code { switch code {
case Success: case Success:
return http.StatusOK return http.StatusOK
case ParamError: // ParamError 和 InvalidParameter 都是 400所以只需要一个 case case ParamError: // ParamError 和 InvalidParameter 都是 400所以只需要一个 case
return http.StatusBadRequest return http.StatusBadRequest
case AuthError, TokenExpired, TokenInvalid: case AuthError, TokenExpired, TokenInvalid:
return http.StatusUnauthorized return http.StatusUnauthorized

View File

@ -21,10 +21,10 @@ type Migration struct {
// MigrationRecord 数据库中的迁移记录 // MigrationRecord 数据库中的迁移记录
type MigrationRecord struct { type MigrationRecord struct {
ID uint `gorm:"primaryKey"` ID uint `gorm:"primaryKey"`
Version string `gorm:"uniqueIndex;size:255;not null"` Version string `gorm:"uniqueIndex;size:255;not null"`
Description string `gorm:"size:500"` Description string `gorm:"size:500"`
Applied bool `gorm:"default:false"` Applied bool `gorm:"default:false"`
AppliedAt time.Time AppliedAt time.Time
CreatedAt time.Time CreatedAt time.Time
UpdatedAt time.Time UpdatedAt time.Time

View File

@ -13,7 +13,7 @@ import (
) )
type Config struct { type Config struct {
Driver string `json:"driver"` // mysql, postgres, sqlite Driver string `json:"driver"` // mysql, postgres, sqlite
Host string `json:"host,optional"` Host string `json:"host,optional"`
Port int `json:"port,optional"` Port int `json:"port,optional"`
Username string `json:"username,optional"` Username string `json:"username,optional"`

View File

@ -15,9 +15,12 @@ const api = axios.create({
api.interceptors.request.use( api.interceptors.request.use(
(config) => { (config) => {
// 可以在这里添加token等认证信息 // 可以在这里添加token等认证信息
const token = localStorage.getItem('token') // 检查是否在浏览器环境中
if (token) { if (typeof window !== 'undefined') {
config.headers.Authorization = `Bearer ${token}` const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
} }
return config return config
}, },
@ -42,9 +45,11 @@ api.interceptors.response.use(
}, },
(error) => { (error) => {
if (error.response?.status === 401) { if (error.response?.status === 401) {
// 处理未授权 // 处理未授权 - 仅在浏览器环境中执行
localStorage.removeItem('token') if (typeof window !== 'undefined') {
window.location.href = '/login' localStorage.removeItem('token')
window.location.href = '/login'
}
} }
return Promise.reject(error) return Promise.reject(error)
} }