450 lines
10 KiB
Go
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
|
|
}
|