代码同步最新节点
This commit is contained in:
parent
5976eda61b
commit
92b93e6037
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -1,67 +0,0 @@
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
type PostHandler struct {
|
|
||||||
db *gorm.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewPostHandler(db *gorm.DB) *PostHandler {
|
|
||||||
return &PostHandler{db: db}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取帖子列表
|
|
||||||
func (h *PostHandler) GetPosts(c *gin.Context) {
|
|
||||||
var posts []Post
|
|
||||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
|
||||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))
|
|
||||||
|
|
||||||
offset := (page - 1) * pageSize
|
|
||||||
query := h.db.Model(&Post{}).Preload("Author")
|
|
||||||
|
|
||||||
var total int64
|
|
||||||
query.Count(&total)
|
|
||||||
|
|
||||||
if err := query.Offset(offset).Limit(pageSize).Find(&posts).Error; err != nil {
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{
|
|
||||||
"code": 500,
|
|
||||||
"message": err.Error(),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
|
||||||
"code": 200,
|
|
||||||
"message": "success",
|
|
||||||
"data": gin.H{
|
|
||||||
"total": total,
|
|
||||||
"posts": posts,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取帖子详情
|
|
||||||
func (h *PostHandler) GetPostDetail(c *gin.Context) {
|
|
||||||
id := c.Param("id")
|
|
||||||
|
|
||||||
var post Post
|
|
||||||
if err := h.db.Preload("Author").First(&post, id).Error; err != nil {
|
|
||||||
c.JSON(http.StatusNotFound, gin.H{
|
|
||||||
"code": 404,
|
|
||||||
"message": "Post not found",
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
|
||||||
"code": 200,
|
|
||||||
"message": "success",
|
|
||||||
"data": post,
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
ALTER TABLE posts
|
|
||||||
ADD COLUMN summary TEXT,
|
|
||||||
ADD COLUMN likes INTEGER DEFAULT 0,
|
|
||||||
ADD COLUMN views INTEGER DEFAULT 0,
|
|
||||||
ADD COLUMN category VARCHAR(50),
|
|
||||||
ADD COLUMN tags TEXT[];
|
|
||||||
|
|
||||||
CREATE TABLE post_likes (
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
post_id INTEGER REFERENCES posts(id),
|
|
||||||
user_id INTEGER REFERENCES users(id),
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
UNIQUE(post_id, user_id)
|
|
||||||
);
|
|
|
@ -1,8 +0,0 @@
|
||||||
DROP TABLE IF EXISTS post_likes;
|
|
||||||
|
|
||||||
ALTER TABLE posts
|
|
||||||
DROP COLUMN IF EXISTS summary,
|
|
||||||
DROP COLUMN IF EXISTS likes,
|
|
||||||
DROP COLUMN IF EXISTS views,
|
|
||||||
DROP COLUMN IF EXISTS category,
|
|
||||||
DROP COLUMN IF EXISTS tags;
|
|
|
@ -1,13 +0,0 @@
|
||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
func InitDB() *gorm.DB {
|
|
||||||
// ... 现有连接代码 ...
|
|
||||||
|
|
||||||
db.AutoMigrate(&Post{})
|
|
||||||
|
|
||||||
return db
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Post struct {
|
|
||||||
ID uint `gorm:"primarykey" json:"id"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Content string `json:"content"`
|
|
||||||
AuthorID uint `json:"authorId"`
|
|
||||||
Author User `gorm:"foreignKey:AuthorID" json:"author"`
|
|
||||||
CreateTime time.Time `gorm:"column:create_time" json:"createTime"`
|
|
||||||
UpdateTime time.Time `gorm:"column:update_time" json:"updateTime"`
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
package routes
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
|
|
||||||
"github.com/your-project/handlers"
|
|
||||||
)
|
|
||||||
|
|
||||||
func SetupRouter(db *gorm.DB) *gin.Engine {
|
|
||||||
router := gin.Default()
|
|
||||||
|
|
||||||
postHandler := handlers.NewPostHandler(db)
|
|
||||||
|
|
||||||
// 帖子相关路由
|
|
||||||
router.GET("/api/posts", postHandler.GetPosts)
|
|
||||||
router.GET("/api/posts/:id", postHandler.GetPostDetail)
|
|
||||||
|
|
||||||
return router
|
|
||||||
}
|
|
|
@ -1,104 +0,0 @@
|
||||||
class PostController {
|
|
||||||
// ... 现有代码 ...
|
|
||||||
|
|
||||||
async getPosts(req: Request, res: Response) {
|
|
||||||
const page = parseInt(req.query.page as string) || 1;
|
|
||||||
const pageSize = parseInt(req.query.pageSize as string) || 10;
|
|
||||||
const category = req.query.category as string;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const result = await this.postModel.findAll({
|
|
||||||
page,
|
|
||||||
pageSize,
|
|
||||||
category
|
|
||||||
});
|
|
||||||
|
|
||||||
res.json({
|
|
||||||
code: 200,
|
|
||||||
message: 'success',
|
|
||||||
data: result
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({
|
|
||||||
code: 500,
|
|
||||||
message: error.message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getPostById(req: Request, res: Response) {
|
|
||||||
const postId = parseInt(req.params.id);
|
|
||||||
const userId = req.user?.id;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const post = await this.postModel.findById(postId, userId);
|
|
||||||
|
|
||||||
res.json({
|
|
||||||
code: 200,
|
|
||||||
message: 'success',
|
|
||||||
data: post
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
res.status(404).json({
|
|
||||||
code: 404,
|
|
||||||
message: error.message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async likePost(req: Request, res: Response) {
|
|
||||||
const postId = parseInt(req.params.id);
|
|
||||||
const userId = req.user.id;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await db.query(
|
|
||||||
`INSERT INTO post_likes (post_id, user_id)
|
|
||||||
VALUES ($1, $2)
|
|
||||||
ON CONFLICT (post_id, user_id) DO NOTHING`,
|
|
||||||
[postId, userId]
|
|
||||||
);
|
|
||||||
|
|
||||||
await db.query(
|
|
||||||
'UPDATE posts SET likes = likes + 1 WHERE id = $1',
|
|
||||||
[postId]
|
|
||||||
);
|
|
||||||
|
|
||||||
res.json({
|
|
||||||
code: 200,
|
|
||||||
message: 'success'
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({
|
|
||||||
code: 500,
|
|
||||||
message: error.message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async unlikePost(req: Request, res: Response) {
|
|
||||||
const postId = parseInt(req.params.id);
|
|
||||||
const userId = req.user.id;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await db.query(
|
|
||||||
'DELETE FROM post_likes WHERE post_id = $1 AND user_id = $2',
|
|
||||||
[postId, userId]
|
|
||||||
);
|
|
||||||
|
|
||||||
await db.query(
|
|
||||||
'UPDATE posts SET likes = likes - 1 WHERE id = $1',
|
|
||||||
[postId]
|
|
||||||
);
|
|
||||||
|
|
||||||
res.json({
|
|
||||||
code: 200,
|
|
||||||
message: 'success'
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({
|
|
||||||
code: 500,
|
|
||||||
message: error.message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,107 +0,0 @@
|
||||||
interface Post {
|
|
||||||
id: number;
|
|
||||||
title: string;
|
|
||||||
content: string;
|
|
||||||
summary: string;
|
|
||||||
authorId: number;
|
|
||||||
createTime: Date;
|
|
||||||
updateTime: Date;
|
|
||||||
likes: number;
|
|
||||||
comments: number;
|
|
||||||
views: number;
|
|
||||||
category: string;
|
|
||||||
tags: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
class PostModel {
|
|
||||||
// ... 现有代码 ...
|
|
||||||
|
|
||||||
async findAll(params: {
|
|
||||||
page: number;
|
|
||||||
pageSize: number;
|
|
||||||
category?: string;
|
|
||||||
}): Promise<{ total: number; posts: Post[] }> {
|
|
||||||
const offset = (params.page - 1) * params.pageSize;
|
|
||||||
const whereClause = params.category ? 'WHERE category = $3' : '';
|
|
||||||
|
|
||||||
const query = `
|
|
||||||
SELECT p.*,
|
|
||||||
u.username, u.avatar,
|
|
||||||
COUNT(c.id) as comments
|
|
||||||
FROM posts p
|
|
||||||
LEFT JOIN users u ON p.author_id = u.id
|
|
||||||
LEFT JOIN comments c ON p.id = c.post_id
|
|
||||||
${whereClause}
|
|
||||||
GROUP BY p.id, u.id
|
|
||||||
ORDER BY p.create_time DESC
|
|
||||||
LIMIT $1 OFFSET $2
|
|
||||||
`;
|
|
||||||
|
|
||||||
const values = params.category
|
|
||||||
? [params.pageSize, offset, params.category]
|
|
||||||
: [params.pageSize, offset];
|
|
||||||
|
|
||||||
const result = await db.query(query, values);
|
|
||||||
const countResult = await db.query(
|
|
||||||
`SELECT COUNT(*) FROM posts ${whereClause}`,
|
|
||||||
params.category ? [params.category] : []
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
total: parseInt(countResult.rows[0].count),
|
|
||||||
posts: result.rows.map(this.transformPostRow)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async findById(id: number, userId?: number): Promise<Post & { likedByMe: boolean }> {
|
|
||||||
const query = `
|
|
||||||
SELECT p.*,
|
|
||||||
u.username, u.avatar,
|
|
||||||
COUNT(c.id) as comments,
|
|
||||||
EXISTS(
|
|
||||||
SELECT 1 FROM post_likes pl
|
|
||||||
WHERE pl.post_id = p.id AND pl.user_id = $2
|
|
||||||
) as liked_by_me
|
|
||||||
FROM posts p
|
|
||||||
LEFT JOIN users u ON p.author_id = u.id
|
|
||||||
LEFT JOIN comments c ON p.id = c.post_id
|
|
||||||
WHERE p.id = $1
|
|
||||||
GROUP BY p.id, u.id
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await db.query(query, [id, userId || null]);
|
|
||||||
if (!result.rows[0]) {
|
|
||||||
throw new Error('Post not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 增加浏览次数
|
|
||||||
await db.query(
|
|
||||||
'UPDATE posts SET views = views + 1 WHERE id = $1',
|
|
||||||
[id]
|
|
||||||
);
|
|
||||||
|
|
||||||
return this.transformPostRow(result.rows[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private transformPostRow(row: any): Post & { likedByMe?: boolean } {
|
|
||||||
return {
|
|
||||||
id: row.id,
|
|
||||||
title: row.title,
|
|
||||||
content: row.content,
|
|
||||||
summary: row.summary,
|
|
||||||
author: {
|
|
||||||
id: row.author_id,
|
|
||||||
username: row.username,
|
|
||||||
avatar: row.avatar
|
|
||||||
},
|
|
||||||
createTime: row.create_time.toISOString(),
|
|
||||||
updateTime: row.update_time.toISOString(),
|
|
||||||
likes: row.likes,
|
|
||||||
comments: parseInt(row.comments),
|
|
||||||
views: row.views,
|
|
||||||
category: row.category,
|
|
||||||
tags: row.tags,
|
|
||||||
likedByMe: row.liked_by_me
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
router.get('/posts', postController.getPosts);
|
|
||||||
router.get('/posts/:id', postController.getPostById);
|
|
||||||
router.post('/posts/:id/like', auth, postController.likePost);
|
|
||||||
router.delete('/posts/:id/like', auth, postController.unlikePost);
|
|
Loading…
Reference in New Issue
Block a user