blob: e01bdd806e350802a672f2c5f5a839e83536a4e4 [file] [log] [blame]
TRM-codingd1cbf672025-06-18 15:15:08 +08001# routes/posts.py
2from flask import Blueprint, request, jsonify, abort
3from extensions import db
4from models.post import Post
5from models.behavior import Behavior
6
7posts_bp = Blueprint('posts', __name__)
8
9@posts_bp.route('', methods=['POST'])
10def create_post():
11 data = request.get_json() or {}
12 post = Post(**data)
13 db.session.add(post)
14 db.session.commit()
15 return jsonify({'id': post.id}), 201
16
17@posts_bp.route('', methods=['GET'])
18def list_posts():
19 posts = Post.query.filter_by(status='published').all()
20 return jsonify([{
21 'id': p.id,
22 'title': p.title,
23 'heat': p.heat,
24 'created_at': p.created_at.isoformat()
25 } for p in posts])
26
27@posts_bp.route('/<int:post_id>', methods=['GET'])
28def get_post(post_id):
29 post = Post.query.get_or_404(post_id)
30 return jsonify({
31 'id': post.id,
32 'user_id': post.user_id,
33 'title': post.title,
34 'content': post.content,
35 'media_urls': post.media_urls,
36 'status': post.status,
37 'heat': post.heat,
38 'created_at': post.created_at.isoformat(),
39 'updated_at': post.updated_at.isoformat()
40 })
41
42@posts_bp.route('/<int:post_id>', methods=['PUT'])
43def update_post(post_id):
44 """
45 修改帖子
46 URL 参数:
47 post_id - 要修改的帖子 ID
48 JSON Body 可选字段:
49 title (string)
50 content (string)
51 topic_id (int) — 必须是 topics 表中已有的 ID
52 media_urls (list) — 字符串数组
53 status (string) — 'draft','pending','published','deleted','rejected'
54 """
55 post = Post.query.get_or_404(post_id)
56 data = request.get_json() or {}
57 # 只更新客户端传来的字段
58 for key in ('title','content','topic_id','media_urls','status'):
59 if key in data:
60 setattr(post, key, data[key])
61 db.session.commit()
62 return '', 204
63
64@posts_bp.route('/<int:post_id>', methods=['DELETE'])
65def delete_post(post_id):
66 post = Post.query.get_or_404(post_id)
67 db.session.delete(post)
68 db.session.commit()
69 return '', 204
70
71
72@posts_bp.route('/<int:post_id>/<action>', methods=['POST'])
73def post_action(post_id, action):
74 """
75 支持的 action: like, favorite, view, share
76 对于 like 和 favorite,保证每个用户每帖只做一次。
77 """
78 if action not in ('like', 'favorite', 'view', 'share'):
79 abort(400, 'Invalid action')
80
81 data = request.get_json() or {}
82 user_id = data.get('user_id')
83 if not user_id:
84 abort(400, 'user_id required')
85
86 # 对 like/favorite 做去重检查
87 if action in ('like', 'favorite'):
88 exists = Behavior.query.filter_by(
89 user_id=user_id,
90 post_id=post_id,
91 type=action
92 ).first()
93 if exists:
94 return jsonify({'error': f'already {action}d'}), 400
95
96 # 创建行为记录
97 beh = Behavior(user_id=user_id, post_id=post_id, type=action)
98 db.session.add(beh)
99
100 # 更新热度
101 post = Post.query.get_or_404(post_id)
102 post.heat += 1
103
104 db.session.commit()
105 return '', 201
106
107
108# 取消点赞
109@posts_bp.route('/<int:post_id>/like', methods=['DELETE'])
110def unlike(post_id):
111 user_id = request.get_json(silent=True) and request.get_json().get('user_id')
112 if not user_id:
113 abort(400, 'user_id required')
114 # 查找已有的 like 行为
115 beh = Behavior.query.filter_by(
116 user_id=user_id,
117 post_id=post_id,
118 type='like'
119 ).first()
120 if not beh:
121 return jsonify({'error': 'not liked yet'}), 400
122
123 db.session.delete(beh)
124 # 更新热度,确保不降到负数
125 post = Post.query.get_or_404(post_id)
126 post.heat = max(post.heat - 1, 0)
127 db.session.commit()
128 return '', 204
129
130# 取消收藏
131@posts_bp.route('/<int:post_id>/favorite', methods=['DELETE'])
132def unfavorite(post_id):
133 user_id = request.get_json(silent=True) and request.get_json().get('user_id')
134 if not user_id:
135 abort(400, 'user_id required')
136 # 查找已有的 favorite 行为
137 beh = Behavior.query.filter_by(
138 user_id=user_id,
139 post_id=post_id,
140 type='favorite'
141 ).first()
142 if not beh:
143 return jsonify({'error': 'not favorited yet'}), 400
144
145 db.session.delete(beh)
146 # 更新热度
147 post = Post.query.get_or_404(post_id)
148 post.heat = max(post.heat - 1, 0)
149 db.session.commit()
150 return '', 204