合并JWL,WZY,TRM代码
Change-Id: Ifb4fcad3c06733e1e005e7d8d9403e3561010fb4
diff --git a/Merge/back_wzy/routes/posts.py b/Merge/back_wzy/routes/posts.py
new file mode 100644
index 0000000..e01bdd8
--- /dev/null
+++ b/Merge/back_wzy/routes/posts.py
@@ -0,0 +1,150 @@
+# routes/posts.py
+from flask import Blueprint, request, jsonify, abort
+from extensions import db
+from models.post import Post
+from models.behavior import Behavior
+
+posts_bp = Blueprint('posts', __name__)
+
+@posts_bp.route('', methods=['POST'])
+def create_post():
+ data = request.get_json() or {}
+ post = Post(**data)
+ db.session.add(post)
+ db.session.commit()
+ return jsonify({'id': post.id}), 201
+
+@posts_bp.route('', methods=['GET'])
+def list_posts():
+ posts = Post.query.filter_by(status='published').all()
+ return jsonify([{
+ 'id': p.id,
+ 'title': p.title,
+ 'heat': p.heat,
+ 'created_at': p.created_at.isoformat()
+ } for p in posts])
+
+@posts_bp.route('/<int:post_id>', methods=['GET'])
+def get_post(post_id):
+ post = Post.query.get_or_404(post_id)
+ return jsonify({
+ 'id': post.id,
+ 'user_id': post.user_id,
+ 'title': post.title,
+ 'content': post.content,
+ 'media_urls': post.media_urls,
+ 'status': post.status,
+ 'heat': post.heat,
+ 'created_at': post.created_at.isoformat(),
+ 'updated_at': post.updated_at.isoformat()
+ })
+
+@posts_bp.route('/<int:post_id>', methods=['PUT'])
+def update_post(post_id):
+ """
+ 修改帖子
+ URL 参数:
+ post_id - 要修改的帖子 ID
+ JSON Body 可选字段:
+ title (string)
+ content (string)
+ topic_id (int) — 必须是 topics 表中已有的 ID
+ media_urls (list) — 字符串数组
+ status (string) — 'draft','pending','published','deleted','rejected'
+ """
+ post = Post.query.get_or_404(post_id)
+ data = request.get_json() or {}
+ # 只更新客户端传来的字段
+ for key in ('title','content','topic_id','media_urls','status'):
+ if key in data:
+ setattr(post, key, data[key])
+ db.session.commit()
+ return '', 204
+
+@posts_bp.route('/<int:post_id>', methods=['DELETE'])
+def delete_post(post_id):
+ post = Post.query.get_or_404(post_id)
+ db.session.delete(post)
+ db.session.commit()
+ return '', 204
+
+
+@posts_bp.route('/<int:post_id>/<action>', methods=['POST'])
+def post_action(post_id, action):
+ """
+ 支持的 action: like, favorite, view, share
+ 对于 like 和 favorite,保证每个用户每帖只做一次。
+ """
+ if action not in ('like', 'favorite', 'view', 'share'):
+ abort(400, 'Invalid action')
+
+ data = request.get_json() or {}
+ user_id = data.get('user_id')
+ if not user_id:
+ abort(400, 'user_id required')
+
+ # 对 like/favorite 做去重检查
+ if action in ('like', 'favorite'):
+ exists = Behavior.query.filter_by(
+ user_id=user_id,
+ post_id=post_id,
+ type=action
+ ).first()
+ if exists:
+ return jsonify({'error': f'already {action}d'}), 400
+
+ # 创建行为记录
+ beh = Behavior(user_id=user_id, post_id=post_id, type=action)
+ db.session.add(beh)
+
+ # 更新热度
+ post = Post.query.get_or_404(post_id)
+ post.heat += 1
+
+ db.session.commit()
+ return '', 201
+
+
+# 取消点赞
+@posts_bp.route('/<int:post_id>/like', methods=['DELETE'])
+def unlike(post_id):
+ user_id = request.get_json(silent=True) and request.get_json().get('user_id')
+ if not user_id:
+ abort(400, 'user_id required')
+ # 查找已有的 like 行为
+ beh = Behavior.query.filter_by(
+ user_id=user_id,
+ post_id=post_id,
+ type='like'
+ ).first()
+ if not beh:
+ return jsonify({'error': 'not liked yet'}), 400
+
+ db.session.delete(beh)
+ # 更新热度,确保不降到负数
+ post = Post.query.get_or_404(post_id)
+ post.heat = max(post.heat - 1, 0)
+ db.session.commit()
+ return '', 204
+
+# 取消收藏
+@posts_bp.route('/<int:post_id>/favorite', methods=['DELETE'])
+def unfavorite(post_id):
+ user_id = request.get_json(silent=True) and request.get_json().get('user_id')
+ if not user_id:
+ abort(400, 'user_id required')
+ # 查找已有的 favorite 行为
+ beh = Behavior.query.filter_by(
+ user_id=user_id,
+ post_id=post_id,
+ type='favorite'
+ ).first()
+ if not beh:
+ return jsonify({'error': 'not favorited yet'}), 400
+
+ db.session.delete(beh)
+ # 更新热度
+ post = Post.query.get_or_404(post_id)
+ post.heat = max(post.heat - 1, 0)
+ db.session.commit()
+ return '', 204
\ No newline at end of file