136 lines
3.0 KiB
Go
136 lines
3.0 KiB
Go
package handler
|
||
|
||
import (
|
||
"database/sql"
|
||
"net/http"
|
||
|
||
"memory/internal/config"
|
||
"memory/internal/middleware"
|
||
"memory/internal/model"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
type SearchHandler struct {
|
||
db *sql.DB
|
||
cfg *config.Config
|
||
}
|
||
|
||
func NewSearchHandler(db *sql.DB, cfg *config.Config) *SearchHandler {
|
||
return &SearchHandler{db: db, cfg: cfg}
|
||
}
|
||
|
||
func (h *SearchHandler) Search(c *gin.Context) {
|
||
userID := middleware.GetUserID(c)
|
||
|
||
var req model.SearchRequest
|
||
if err := c.ShouldBindQuery(&req); err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||
return
|
||
}
|
||
|
||
if req.Page < 1 {
|
||
req.Page = 1
|
||
}
|
||
if req.PageSize < 1 || req.PageSize > 50 {
|
||
req.PageSize = 20
|
||
}
|
||
offset := (req.Page - 1) * req.PageSize
|
||
|
||
// 构建查询
|
||
query := `
|
||
SELECT p.id, p.user_id, p.content, p.created_at,
|
||
u.id, u.username, u.nickname, u.avatar_url,
|
||
(SELECT COUNT(*) FROM likes WHERE post_id = p.id) as like_count,
|
||
(SELECT COUNT(*) FROM likes WHERE post_id = p.id AND user_id = ?) as liked,
|
||
(SELECT COUNT(*) FROM comments WHERE post_id = p.id) as comment_count
|
||
FROM posts p
|
||
JOIN users u ON p.user_id = u.id
|
||
WHERE 1=1
|
||
`
|
||
args := []interface{}{userID}
|
||
|
||
if req.Query != "" {
|
||
query += " AND p.content LIKE ?"
|
||
args = append(args, "%"+req.Query+"%")
|
||
}
|
||
|
||
if req.StartDate != "" {
|
||
query += " AND DATE(p.created_at) >= ?"
|
||
args = append(args, req.StartDate)
|
||
}
|
||
|
||
if req.EndDate != "" {
|
||
query += " AND DATE(p.created_at) <= ?"
|
||
args = append(args, req.EndDate)
|
||
}
|
||
|
||
query += " ORDER BY p.created_at DESC LIMIT ? OFFSET ?"
|
||
args = append(args, req.PageSize, offset)
|
||
|
||
rows, err := h.db.Query(query, args...)
|
||
if err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": "database error"})
|
||
return
|
||
}
|
||
defer rows.Close()
|
||
|
||
posts := []model.Post{}
|
||
for rows.Next() {
|
||
var post model.Post
|
||
var user model.User
|
||
var liked int
|
||
err := rows.Scan(
|
||
&post.ID, &post.UserID, &post.Content, &post.CreatedAt,
|
||
&user.ID, &user.Username, &user.Nickname, &user.AvatarURL,
|
||
&post.LikeCount, &liked, &post.CommentCount,
|
||
)
|
||
if err != nil {
|
||
continue
|
||
}
|
||
post.User = &user
|
||
post.Liked = liked > 0
|
||
posts = append(posts, post)
|
||
}
|
||
|
||
c.JSON(http.StatusOK, posts)
|
||
}
|
||
|
||
// 获取热力图数据(GitHub 风格)
|
||
func (h *SearchHandler) Heatmap(c *gin.Context) {
|
||
year := c.DefaultQuery("year", "")
|
||
|
||
query := `
|
||
SELECT DATE(created_at) as date, COUNT(*) as count
|
||
FROM posts
|
||
WHERE 1=1
|
||
`
|
||
args := []interface{}{}
|
||
|
||
if year != "" {
|
||
query += " AND strftime('%Y', created_at) = ?"
|
||
args = append(args, year)
|
||
} else {
|
||
// 默认最近一年
|
||
query += " AND created_at >= DATE('now', '-1 year')"
|
||
}
|
||
|
||
query += " GROUP BY DATE(created_at) ORDER BY date"
|
||
|
||
rows, err := h.db.Query(query, args...)
|
||
if err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": "database error"})
|
||
return
|
||
}
|
||
defer rows.Close()
|
||
|
||
data := []model.HeatmapData{}
|
||
for rows.Next() {
|
||
var item model.HeatmapData
|
||
rows.Scan(&item.Date, &item.Count)
|
||
data = append(data, item)
|
||
}
|
||
|
||
c.JSON(http.StatusOK, data)
|
||
}
|