Files
nl-blogs/server/repositories/post_repository.go
2026-01-16 09:32:46 +08:00

450 lines
10 KiB
Go

package repositories
import (
"database/sql"
"log"
"github.com/niangaodev/art-code/config"
"github.com/niangaodev/art-code/models"
)
// GetPosts 获取所有博客文章(支持搜索)
func GetPosts(keyword string) ([]models.Post, error) {
var rows *sql.Rows
var err error
if keyword != "" {
// 使用全文搜索
query := `
SELECT id, title, category, date, excerpt, content, read_count, is_published, created_at, updated_at
FROM posts
WHERE is_published = 1 AND (
MATCH(title, content) AGAINST(? IN BOOLEAN MODE) OR
title LIKE ? OR
content LIKE ?
)
ORDER BY created_at DESC
`
likeKeyword := "%" + keyword + "%"
rows, err = config.DB.Query(query, keyword, likeKeyword, likeKeyword)
} else {
// 默认查询
query := "SELECT id, title, category, date, excerpt, content, read_count, is_published, created_at, updated_at FROM posts WHERE is_published = 1 ORDER BY created_at DESC"
rows, err = config.DB.Query(query)
}
if err != nil {
log.Printf("Error querying posts: %v", err)
return nil, err
}
defer rows.Close()
var posts []models.Post
for rows.Next() {
var post models.Post
if err := rows.Scan(
&post.ID,
&post.Title,
&post.Category,
&post.Date,
&post.Excerpt,
&post.Content,
&post.ReadCount,
&post.IsPublished,
&post.CreatedAt,
&post.UpdatedAt,
); err != nil {
log.Printf("Error scanning post: %v", err)
continue
}
posts = append(posts, post)
}
return posts, nil
}
// GetPostByID 根据ID获取博客文章
func GetPostByID(id uint) (*models.Post, error) {
query := "SELECT id, title, category, date, excerpt, content, read_count, is_published, created_at, updated_at FROM posts WHERE id = ? AND is_published = 1"
row := config.DB.QueryRow(query, id)
var post models.Post
if err := row.Scan(
&post.ID,
&post.Title,
&post.Category,
&post.Date,
&post.Excerpt,
&post.Content,
&post.ReadCount,
&post.IsPublished,
&post.CreatedAt,
&post.UpdatedAt,
); err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
log.Printf("Error scanning post by ID: %v", err)
return nil, err
}
// 更新阅读量
updateReadCountQuery := "UPDATE posts SET read_count = read_count + 1 WHERE id = ?"
if _, err := config.DB.Exec(updateReadCountQuery, id); err != nil {
log.Printf("Error updating post read count: %v", err)
}
return &post, nil
}
// GetAllPosts 获取所有博客文章(包括未发布的)
func GetAllPosts() ([]models.Post, error) {
query := "SELECT id, title, category, date, excerpt, content, read_count, is_published, created_at, updated_at FROM posts ORDER BY created_at DESC"
rows, err := config.DB.Query(query)
if err != nil {
log.Printf("Error querying all posts: %v", err)
return nil, err
}
defer rows.Close()
var posts []models.Post
for rows.Next() {
var post models.Post
if err := rows.Scan(
&post.ID,
&post.Title,
&post.Category,
&post.Date,
&post.Excerpt,
&post.Content,
&post.ReadCount,
&post.IsPublished,
&post.CreatedAt,
&post.UpdatedAt,
); err != nil {
log.Printf("Error scanning post: %v", err)
continue
}
posts = append(posts, post)
}
return posts, nil
}
// CreatePost 创建博客文章
func CreatePost(post *models.Post) error {
query := `
INSERT INTO posts (title, category, date, excerpt, content, is_published, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, NOW(), NOW())
`
result, err := config.DB.Exec(
query,
post.Title,
post.Category,
post.Date,
post.Excerpt,
post.Content,
post.IsPublished,
)
if err != nil {
log.Printf("Error creating post: %v", err)
return err
}
id, err := result.LastInsertId()
if err != nil {
return err
}
post.ID = uint(id)
return nil
}
// UpdatePost 更新博客文章
func UpdatePost(post *models.Post) error {
query := `
UPDATE posts SET title = ?, category = ?, date = ?, excerpt = ?, content = ?, is_published = ?, updated_at = NOW()
WHERE id = ?
`
_, err := config.DB.Exec(
query,
post.Title,
post.Category,
post.Date,
post.Excerpt,
post.Content,
post.IsPublished,
post.ID,
)
if err != nil {
log.Printf("Error updating post: %v", err)
return err
}
return nil
}
// DeletePost 删除博客文章
func DeletePost(id uint) error {
query := "DELETE FROM posts WHERE id = ?"
_, err := config.DB.Exec(query, id)
if err != nil {
log.Printf("Error deleting post: %v", err)
return err
}
return nil
}
// GetPostCount 获取文章总数
func GetPostCount() (int, error) {
var count int
query := "SELECT COUNT(*) FROM posts"
row := config.DB.QueryRow(query)
err := row.Scan(&count)
if err != nil {
log.Printf("Error getting post count: %v", err)
return 0, err
}
return count, nil
}
// BuildPostResponse 构建博客文章响应
func BuildPostResponse(post *models.Post, includeContent bool) *models.PostResponse {
response := &models.PostResponse{
ID: post.ID,
Title: post.Title,
Category: post.Category,
Date: post.Date,
Excerpt: post.Excerpt,
}
if includeContent {
response.Content = post.Content
}
return response
}
// BuildPostsResponse 构建博客文章列表响应
func BuildPostsResponse(posts []models.Post) []models.PostResponse {
var responses []models.PostResponse
for _, post := range posts {
responses = append(responses, *BuildPostResponse(&post, false))
}
return responses
}
// SavePostHistory 保存文章历史记录
func SavePostHistory(post *models.Post, modifiedBy uint) error {
// 获取当前最大版本号
var maxVersion uint
query := "SELECT COALESCE(MAX(version), 0) FROM post_history WHERE post_id = ?"
if err := config.DB.QueryRow(query, post.ID).Scan(&maxVersion); err != nil {
log.Printf("Error getting max version: %v", err)
return err
}
// 插入新的历史记录
insertQuery := `
INSERT INTO post_history (
post_id, version, title, category, date, excerpt, content,
is_published, modified_by, modified_at, created_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
`
_, err := config.DB.Exec(
insertQuery,
post.ID,
maxVersion+1,
post.Title,
post.Category,
post.Date,
post.Excerpt,
post.Content,
post.IsPublished,
modifiedBy,
)
if err != nil {
log.Printf("Error saving post history: %v", err)
return err
}
return nil
}
// GetPostHistory 获取文章历史记录
func GetPostHistory(postID uint) ([]models.PostHistory, error) {
query := `
SELECT id, post_id, version, title, category, date, excerpt, content,
is_published, modified_by, modified_at, created_at
FROM post_history
WHERE post_id = ?
ORDER BY version DESC
`
rows, err := config.DB.Query(query, postID)
if err != nil {
log.Printf("Error querying post history: %v", err)
return nil, err
}
defer rows.Close()
var history []models.PostHistory
for rows.Next() {
var h models.PostHistory
if err := rows.Scan(
&h.ID,
&h.PostID,
&h.Version,
&h.Title,
&h.Category,
&h.Date, // Scan date directly into h.Date
&h.Excerpt,
&h.Content,
&h.IsPublished,
&h.ModifiedBy,
&h.ModifiedAt,
&h.CreatedAt,
); err != nil {
log.Printf("Error scanning post history: %v", err)
continue
}
history = append(history, h)
}
return history, nil
}
// GetPostHistoryByVersion 获取指定版本的文章历史记录
func GetPostHistoryByVersion(postID uint, version uint) (*models.PostHistory, error) {
query := `
SELECT id, post_id, version, title, category, date, excerpt, content,
is_published, modified_by, modified_at, created_at
FROM post_history
WHERE post_id = ? AND version = ?
`
row := config.DB.QueryRow(query, postID, version)
var h models.PostHistory
if err := row.Scan(
&h.ID,
&h.PostID,
&h.Version,
&h.Title,
&h.Category,
&h.Date,
&h.Excerpt,
&h.Content,
&h.IsPublished,
&h.ModifiedBy,
&h.ModifiedAt,
&h.CreatedAt,
); err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
log.Printf("Error scanning post history by version: %v", err)
return nil, err
}
return &h, nil
}
// BuildPostHistoryResponse 构建文章历史记录响应
func BuildPostHistoryResponse(history *models.PostHistory) *models.PostHistoryResponse {
return &models.PostHistoryResponse{
ID: history.ID,
PostID: history.PostID,
Version: history.Version,
Title: history.Title,
Category: history.Category,
Date: history.Date,
IsPublished: history.IsPublished,
ModifiedBy: history.ModifiedBy,
ModifiedAt: history.ModifiedAt.Format("2006-01-02 15:04:05"),
CreatedAt: history.CreatedAt.Format("2006-01-02 15:04:05"),
}
}
// BuildPostHistoryResponses 构建文章历史记录列表响应
func BuildPostHistoryResponses(history []models.PostHistory) []models.PostHistoryResponse {
var responses []models.PostHistoryResponse
for _, h := range history {
responses = append(responses, *BuildPostHistoryResponse(&h))
}
return responses
}
// GetNewPostsTrend 获取最近7天新增文章趋势
func GetNewPostsTrend() ([]struct {
Date string
Count int
}, error) {
query := `
SELECT DATE_FORMAT(created_at, '%Y-%m-%d') as date, COUNT(*) as count
FROM posts
WHERE created_at >= DATE_SUB(CURDATE(), INTERVAL 6 DAY)
GROUP BY date
ORDER BY date ASC
`
rows, err := config.DB.Query(query)
if err != nil {
return nil, err
}
defer rows.Close()
var results []struct {
Date string
Count int
}
for rows.Next() {
var r struct {
Date string
Count int
}
if err := rows.Scan(&r.Date, &r.Count); err != nil {
return nil, err
}
results = append(results, r)
}
return results, nil
}
// GetTopPosts 获取热门文章 (按阅读量)
func GetTopPosts(limit int) ([]models.Post, error) {
query := `
SELECT id, title, category, date, excerpt, content, read_count, is_published, created_at, updated_at
FROM posts
WHERE is_published = 1
ORDER BY read_count DESC
LIMIT ?
`
rows, err := config.DB.Query(query, limit)
if err != nil {
return nil, err
}
defer rows.Close()
var posts []models.Post
for rows.Next() {
var post models.Post
if err := rows.Scan(
&post.ID,
&post.Title,
&post.Category,
&post.Date,
&post.Excerpt,
&post.Content,
&post.ReadCount,
&post.IsPublished,
&post.CreatedAt,
&post.UpdatedAt,
); err != nil {
continue
}
posts = append(posts, post)
}
return posts, nil
}