302 lines
6.5 KiB
Go
302 lines
6.5 KiB
Go
package repositories
|
||
|
||
import (
|
||
"database/sql"
|
||
"log"
|
||
|
||
"github.com/niangaodev/art-code/config"
|
||
"github.com/niangaodev/art-code/models"
|
||
)
|
||
|
||
// GetWorks 获取所有作品
|
||
func GetWorks() ([]models.Work, error) {
|
||
query := "SELECT id, title, category, year, hero_img, description, is_featured, created_at, updated_at FROM works"
|
||
rows, err := config.DB.Query(query)
|
||
if err != nil {
|
||
log.Printf("Error querying works: %v", err)
|
||
return nil, err
|
||
}
|
||
defer rows.Close()
|
||
|
||
var works []models.Work
|
||
for rows.Next() {
|
||
var work models.Work
|
||
if err := rows.Scan(
|
||
&work.ID,
|
||
&work.Title,
|
||
&work.Category,
|
||
&work.Year,
|
||
&work.HeroImg,
|
||
&work.Description,
|
||
&work.IsFeatured,
|
||
&work.CreatedAt,
|
||
&work.UpdatedAt,
|
||
); err != nil {
|
||
log.Printf("Error scanning work: %v", err)
|
||
continue
|
||
}
|
||
works = append(works, work)
|
||
}
|
||
|
||
return works, nil
|
||
}
|
||
|
||
// GetWorkByID 根据ID获取作品
|
||
func GetWorkByID(id string) (*models.Work, error) {
|
||
query := "SELECT id, title, category, year, hero_img, description, is_featured, created_at, updated_at FROM works WHERE id = ?"
|
||
row := config.DB.QueryRow(query, id)
|
||
|
||
var work models.Work
|
||
if err := row.Scan(
|
||
&work.ID,
|
||
&work.Title,
|
||
&work.Category,
|
||
&work.Year,
|
||
&work.HeroImg,
|
||
&work.Description,
|
||
&work.IsFeatured,
|
||
&work.CreatedAt,
|
||
&work.UpdatedAt,
|
||
); err != nil {
|
||
if err == sql.ErrNoRows {
|
||
return nil, nil
|
||
}
|
||
log.Printf("Error scanning work by ID: %v", err)
|
||
return nil, err
|
||
}
|
||
|
||
return &work, nil
|
||
}
|
||
|
||
// GetWorkTechStack 获取作品的技术栈
|
||
func GetWorkTechStack(workID string) ([]models.WorkTechStack, error) {
|
||
query := "SELECT id, work_id, category, item, created_at FROM work_tech_stack WHERE work_id = ?"
|
||
rows, err := config.DB.Query(query, workID)
|
||
if err != nil {
|
||
log.Printf("Error querying work tech stack: %v", err)
|
||
return nil, err
|
||
}
|
||
defer rows.Close()
|
||
|
||
var techStacks []models.WorkTechStack
|
||
for rows.Next() {
|
||
var techStack models.WorkTechStack
|
||
if err := rows.Scan(
|
||
&techStack.ID,
|
||
&techStack.WorkID,
|
||
&techStack.Category,
|
||
&techStack.Item,
|
||
&techStack.CreatedAt,
|
||
); err != nil {
|
||
log.Printf("Error scanning work tech stack: %v", err)
|
||
continue
|
||
}
|
||
techStacks = append(techStacks, techStack)
|
||
}
|
||
|
||
return techStacks, nil
|
||
}
|
||
|
||
// GetWorkGallery 获取作品的图库
|
||
func GetWorkGallery(workID string) ([]models.WorkGallery, error) {
|
||
query := "SELECT id, work_id, image_url, sort_order, description, created_at FROM work_gallery WHERE work_id = ? ORDER BY sort_order"
|
||
rows, err := config.DB.Query(query, workID)
|
||
if err != nil {
|
||
log.Printf("Error querying work gallery: %v", err)
|
||
return nil, err
|
||
}
|
||
defer rows.Close()
|
||
|
||
var galleries []models.WorkGallery
|
||
for rows.Next() {
|
||
var gallery models.WorkGallery
|
||
if err := rows.Scan(
|
||
&gallery.ID,
|
||
&gallery.WorkID,
|
||
&gallery.ImageURL,
|
||
&gallery.SortOrder,
|
||
&gallery.Description,
|
||
&gallery.CreatedAt,
|
||
); err != nil {
|
||
log.Printf("Error scanning work gallery: %v", err)
|
||
continue
|
||
}
|
||
galleries = append(galleries, gallery)
|
||
}
|
||
|
||
return galleries, nil
|
||
}
|
||
|
||
// BuildWorkResponse 构建作品响应,包含关联数据
|
||
func BuildWorkResponse(work *models.Work) (*models.WorkResponse, error) {
|
||
// 获取技术栈
|
||
techStacks, err := GetWorkTechStack(work.ID)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 按类别分组技术栈
|
||
techStackMap := make(map[string][]string)
|
||
for _, ts := range techStacks {
|
||
techStackMap[ts.Category] = append(techStackMap[ts.Category], ts.Item)
|
||
}
|
||
|
||
// 转换为前端期望的格式
|
||
var techStackResponse []map[string]interface{}
|
||
for category, items := range techStackMap {
|
||
techStackResponse = append(techStackResponse, map[string]interface{}{
|
||
"category": category,
|
||
"items": items,
|
||
})
|
||
}
|
||
|
||
// 获取图库
|
||
galleries, err := GetWorkGallery(work.ID)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 提取图片URL
|
||
var galleryImages []string
|
||
for _, g := range galleries {
|
||
galleryImages = append(galleryImages, g.ImageURL)
|
||
}
|
||
|
||
// 获取下一个作品ID
|
||
nextWorkID, err := GetNextWorkID(work.ID)
|
||
if err != nil {
|
||
log.Printf("Error getting next work ID: %v", err)
|
||
nextWorkID = ""
|
||
}
|
||
|
||
return &models.WorkResponse{
|
||
ID: work.ID,
|
||
Title: work.Title,
|
||
Category: work.Category,
|
||
Year: work.Year,
|
||
HeroImg: work.HeroImg,
|
||
Desc: work.Description,
|
||
TechStack: techStackResponse,
|
||
Gallery: galleryImages,
|
||
Links: map[string]interface{}{
|
||
"live": "#",
|
||
},
|
||
Next: nextWorkID,
|
||
}, nil
|
||
}
|
||
|
||
// GetNextWorkID 获取下一个作品ID(简单实现,实际可能需要更复杂的逻辑)
|
||
func GetNextWorkID(currentID string) (string, error) {
|
||
// 获取所有作品ID
|
||
query := "SELECT id FROM works"
|
||
rows, err := config.DB.Query(query)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
defer rows.Close()
|
||
|
||
var ids []string
|
||
for rows.Next() {
|
||
var id string
|
||
if err := rows.Scan(&id); err != nil {
|
||
continue
|
||
}
|
||
ids = append(ids, id)
|
||
}
|
||
|
||
// 找到当前ID的索引
|
||
index := -1
|
||
for i, id := range ids {
|
||
if id == currentID {
|
||
index = i
|
||
break
|
||
}
|
||
}
|
||
|
||
// 如果没找到或者是最后一个,返回第一个
|
||
if index == -1 || index == len(ids)-1 {
|
||
if len(ids) > 0 {
|
||
return ids[0], nil
|
||
}
|
||
return "", nil
|
||
}
|
||
|
||
// 返回下一个
|
||
return ids[index+1], nil
|
||
}
|
||
|
||
// CreateWork 创建作品
|
||
func CreateWork(work *models.Work) error {
|
||
query := `
|
||
INSERT INTO works (id, title, category, year, hero_img, description, is_featured, created_at, updated_at)
|
||
VALUES (?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
|
||
`
|
||
_, err := config.DB.Exec(
|
||
query,
|
||
work.ID,
|
||
work.Title,
|
||
work.Category,
|
||
work.Year,
|
||
work.HeroImg,
|
||
work.Description,
|
||
work.IsFeatured,
|
||
)
|
||
if err != nil {
|
||
log.Printf("Error creating work: %v", err)
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// UpdateWork 更新作品
|
||
func UpdateWork(work *models.Work) error {
|
||
query := `
|
||
UPDATE works SET title = ?, category = ?, year = ?, hero_img = ?, description = ?, is_featured = ?, updated_at = NOW()
|
||
WHERE id = ?
|
||
`
|
||
_, err := config.DB.Exec(
|
||
query,
|
||
work.Title,
|
||
work.Category,
|
||
work.Year,
|
||
work.HeroImg,
|
||
work.Description,
|
||
work.IsFeatured,
|
||
work.ID,
|
||
)
|
||
if err != nil {
|
||
log.Printf("Error updating work: %v", err)
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// DeleteWork 删除作品
|
||
func DeleteWork(id string) error {
|
||
query := "DELETE FROM works WHERE id = ?"
|
||
_, err := config.DB.Exec(query, id)
|
||
if err != nil {
|
||
log.Printf("Error deleting work: %v", err)
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// GetWorkCount 获取作品总数
|
||
func GetWorkCount() (int, error) {
|
||
var count int
|
||
query := "SELECT COUNT(*) FROM works"
|
||
row := config.DB.QueryRow(query)
|
||
|
||
err := row.Scan(&count)
|
||
if err != nil {
|
||
log.Printf("Error getting work count: %v", err)
|
||
return 0, err
|
||
}
|
||
|
||
return count, nil
|
||
}
|