feat: 实现后端和管理后台基础架构
## 后端架构 (Go + Gin + GORM) - ✅ 完整的分层架构 (API/Service/Repository) - ✅ PostgreSQL数据库设计和迁移脚本 - ✅ JWT认证系统和权限控制 - ✅ 用户、照片、分类、标签等核心模型 - ✅ 中间件系统 (认证、CORS、日志) - ✅ 配置管理和环境变量支持 - ✅ 结构化日志和错误处理 - ✅ Makefile构建和部署脚本 ## 管理后台架构 (React + TypeScript) - ✅ Vite + React 18 + TypeScript现代化架构 - ✅ 路由系统和状态管理 (Zustand + TanStack Query) - ✅ 基于Radix UI的组件库基础 - ✅ 认证流程和权限控制 - ✅ 响应式设计和主题系统 ## 数据库设计 - ✅ 用户表 (角色权限、认证信息) - ✅ 照片表 (元数据、EXIF、状态管理) - ✅ 分类表 (层级结构、封面图片) - ✅ 标签表 (使用统计、标签云) - ✅ 关联表 (照片-标签多对多) ## 技术特点 - 🚀 高性能: Gin框架 + GORM ORM - 🔐 安全: JWT认证 + 密码加密 + 权限控制 - 📊 监控: 结构化日志 + 健康检查 - 🎨 现代化: React 18 + TypeScript + Vite - 📱 响应式: Tailwind CSS + Radix UI 参考文档: docs/development/saved-docs/
This commit is contained in:
85
backend/internal/models/category.go
Normal file
85
backend/internal/models/category.go
Normal file
@ -0,0 +1,85 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// Category 分类模型
|
||||
type Category struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Name string `gorm:"size:100;not null" json:"name"`
|
||||
Description string `gorm:"type:text" json:"description"`
|
||||
ParentID *uint `json:"parent_id"`
|
||||
Parent *Category `gorm:"foreignKey:ParentID" json:"parent,omitempty"`
|
||||
Children []Category `gorm:"foreignKey:ParentID" json:"children,omitempty"`
|
||||
Color string `gorm:"size:7;default:#3b82f6" json:"color"`
|
||||
CoverImage string `gorm:"size:500" json:"cover_image"`
|
||||
Sort int `gorm:"default:0" json:"sort"`
|
||||
IsActive bool `gorm:"default:true" json:"is_active"`
|
||||
PhotoCount int `gorm:"-" json:"photo_count"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||
}
|
||||
|
||||
// TableName 返回分类表名
|
||||
func (Category) TableName() string {
|
||||
return "categories"
|
||||
}
|
||||
|
||||
// CreateCategoryRequest 创建分类请求
|
||||
type CreateCategoryRequest struct {
|
||||
Name string `json:"name" binding:"required,max=100"`
|
||||
Description string `json:"description"`
|
||||
ParentID *uint `json:"parent_id"`
|
||||
Color string `json:"color" binding:"omitempty,hexcolor"`
|
||||
CoverImage string `json:"cover_image" binding:"omitempty,max=500"`
|
||||
Sort int `json:"sort"`
|
||||
}
|
||||
|
||||
// UpdateCategoryRequest 更新分类请求
|
||||
type UpdateCategoryRequest struct {
|
||||
Name *string `json:"name" binding:"omitempty,max=100"`
|
||||
Description *string `json:"description"`
|
||||
ParentID *uint `json:"parent_id"`
|
||||
Color *string `json:"color" binding:"omitempty,hexcolor"`
|
||||
CoverImage *string `json:"cover_image" binding:"omitempty,max=500"`
|
||||
Sort *int `json:"sort"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
}
|
||||
|
||||
// CategoryListParams 分类列表查询参数
|
||||
type CategoryListParams struct {
|
||||
IncludeStats bool `form:"include_stats"`
|
||||
IncludeTree bool `form:"include_tree"`
|
||||
ParentID uint `form:"parent_id"`
|
||||
IsActive bool `form:"is_active"`
|
||||
}
|
||||
|
||||
// CategoryResponse 分类响应
|
||||
type CategoryResponse struct {
|
||||
*Category
|
||||
}
|
||||
|
||||
// CategoryTreeNode 分类树节点
|
||||
type CategoryTreeNode struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
PhotoCount int `json:"photo_count"`
|
||||
Children []CategoryTreeNode `json:"children"`
|
||||
}
|
||||
|
||||
// CategoryListResponse 分类列表响应
|
||||
type CategoryListResponse struct {
|
||||
Categories []CategoryResponse `json:"categories"`
|
||||
Tree []CategoryTreeNode `json:"tree,omitempty"`
|
||||
Stats *CategoryStats `json:"stats,omitempty"`
|
||||
}
|
||||
|
||||
// CategoryStats 分类统计
|
||||
type CategoryStats struct {
|
||||
TotalCategories int `json:"total_categories"`
|
||||
MaxLevel int `json:"max_level"`
|
||||
FeaturedCount int `json:"featured_count"`
|
||||
}
|
||||
Reference in New Issue
Block a user