feat(material): add material handling and routing functionality
Some checks failed
Build Backend / build (push) Failing after 12m1s
Build Backend / build-docker (push) Has been skipped

- Introduced MaterialHandler for managing learning materials and subjects.
- Updated router to include routes for public and admin material management.
- Enhanced database initialization with material subject and file models.
- Implemented seeding logic for material subjects and files.
- Updated wire generation to include MaterialHandler and related services.
This commit is contained in:
lafay
2026-03-25 20:44:12 +08:00
parent 28a45caad3
commit 0ef8e5a7e1
10 changed files with 1122 additions and 22 deletions

113
internal/model/material.go Normal file
View File

@@ -0,0 +1,113 @@
package model
import (
"database/sql/driver"
"encoding/json"
"time"
"github.com/google/uuid"
"gorm.io/gorm"
)
// MaterialFileType 文件类型
type MaterialFileType string
const (
MaterialFileTypePDF MaterialFileType = "pdf"
MaterialFileTypeWord MaterialFileType = "word"
MaterialFileTypePPT MaterialFileType = "ppt"
)
// MaterialStatus 资料状态
type MaterialStatus string
const (
MaterialStatusActive MaterialStatus = "active"
MaterialStatusInactive MaterialStatus = "inactive"
)
// MaterialSubject 学科分类
type MaterialSubject struct {
ID string `json:"id" gorm:"type:varchar(36);primaryKey"`
Name string `json:"name" gorm:"type:varchar(100);not null"`
Icon string `json:"icon" gorm:"type:varchar(50)"` // MaterialCommunityIcons name
Color string `json:"color" gorm:"type:varchar(20)"` // 主题色
Description string `json:"description" gorm:"type:varchar(255)"` // 描述
SortOrder int `json:"sort_order" gorm:"default:0;index"` // 排序权重
IsActive bool `json:"is_active" gorm:"default:true;index"` // 是否启用
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"`
UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"`
// 关联
Materials []MaterialFile `json:"materials,omitempty" gorm:"foreignKey:SubjectID"`
}
// BeforeCreate 创建前生成UUID
func (s *MaterialSubject) BeforeCreate(tx *gorm.DB) error {
if s.ID == "" {
s.ID = uuid.New().String()
}
return nil
}
func (MaterialSubject) TableName() string {
return "material_subjects"
}
// StringArray 字符串数组类型用于tags
type StringArray []string
// Value 实现 driver.Valuer 接口
func (a StringArray) Value() (driver.Value, error) {
if a == nil {
return nil, nil
}
return json.Marshal(a)
}
// Scan 实现 sql.Scanner 接口
func (a *StringArray) Scan(value interface{}) error {
if value == nil {
*a = nil
return nil
}
bytes, ok := value.([]byte)
if !ok {
return nil
}
return json.Unmarshal(bytes, a)
}
// MaterialFile 文件资料
type MaterialFile struct {
ID string `json:"id" gorm:"type:varchar(36);primaryKey"`
SubjectID string `json:"subject_id" gorm:"type:varchar(36);index;not null"`
Title string `json:"title" gorm:"type:varchar(200);not null"`
Description string `json:"description" gorm:"type:text"`
FileType MaterialFileType `json:"file_type" gorm:"type:varchar(20);not null;index"`
FileSize int64 `json:"file_size" gorm:"default:0"` // 文件大小(字节)
FileURL string `json:"file_url" gorm:"type:text;not null"` // 文件URL
FileName string `json:"file_name" gorm:"type:varchar(255)"` // 原始文件名
DownloadCount int `json:"download_count" gorm:"default:0"` // 下载次数
AuthorID string `json:"author_id" gorm:"type:varchar(36);index"` // 上传者ID
Tags StringArray `json:"tags" gorm:"type:json"` // 标签
Status MaterialStatus `json:"status" gorm:"type:varchar(20);default:active;index"` // 状态
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime;index"`
UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"`
// 关联
Subject *MaterialSubject `json:"subject,omitempty" gorm:"foreignKey:SubjectID"`
Author *User `json:"author,omitempty" gorm:"foreignKey:AuthorID"`
}
// BeforeCreate 创建前生成UUID
func (f *MaterialFile) BeforeCreate(tx *gorm.DB) error {
if f.ID == "" {
f.ID = uuid.New().String()
}
return nil
}
func (MaterialFile) TableName() string {
return "material_files"
}