This commit is contained in:
刘正航
2026-04-21 22:45:19 +08:00
commit b5237f9038
159 changed files with 7769 additions and 0 deletions

View File

@@ -0,0 +1,135 @@
import json
from pathlib import Path
from flask import Blueprint, current_app, request
from flask_jwt_extended import jwt_required
from app.extensions import db
from app.models import Recipe
from app.utils.auth import admin_required
from app.utils.response import fail, ok
recipe_bp = Blueprint("recipe", __name__)
def _recipe_payload(recipe: Recipe, payload: dict) -> None:
recipe.name = payload.get("name", recipe.name)
recipe.category = payload.get("category", recipe.category or "轻食")
recipe.description = payload.get("description", recipe.description or "")
recipe.calories = float(payload.get("calories", recipe.calories or 0))
recipe.protein = float(payload.get("protein", recipe.protein or 0))
recipe.fat = float(payload.get("fat", recipe.fat or 0))
recipe.carbs = float(payload.get("carbs", recipe.carbs or 0))
recipe.fiber = float(payload.get("fiber", recipe.fiber or 0))
recipe.tags = payload.get("tags", recipe.tags or [])
recipe.difficulty = payload.get("difficulty", recipe.difficulty or "easy")
@recipe_bp.get("")
@jwt_required(optional=True)
def list_recipes():
keyword = (request.args.get("keyword") or "").strip()
category = (request.args.get("category") or "").strip()
page = max(int(request.args.get("page", 1) or 1), 1)
page_size = min(max(int(request.args.get("page_size", 10) or 10), 1), 50)
query = Recipe.query
if keyword:
query = query.filter(Recipe.name.like(f"%{keyword}%"))
if category:
query = query.filter(Recipe.category == category)
pagination = query.order_by(Recipe.id.desc()).paginate(page=page, per_page=page_size, error_out=False)
data = {
"items": [item.to_dict() for item in pagination.items],
"total": pagination.total,
"page": page,
"page_size": page_size,
}
return ok(data)
@recipe_bp.get("/<int:recipe_id>")
@jwt_required(optional=True)
def get_recipe(recipe_id: int):
recipe = Recipe.query.get(recipe_id)
if not recipe:
return fail("食谱不存在", 404)
return ok(recipe.to_dict())
@recipe_bp.post("")
@admin_required
def create_recipe():
payload = request.get_json(silent=True) or {}
if not payload.get("name"):
return fail("缺少食谱名称", 400)
recipe = Recipe()
_recipe_payload(recipe, payload)
db.session.add(recipe)
db.session.commit()
return ok(recipe.to_dict(), "食谱创建成功")
@recipe_bp.put("/<int:recipe_id>")
@admin_required
def update_recipe(recipe_id: int):
recipe = Recipe.query.get(recipe_id)
if not recipe:
return fail("食谱不存在", 404)
payload = request.get_json(silent=True) or {}
_recipe_payload(recipe, payload)
db.session.commit()
return ok(recipe.to_dict(), "食谱更新成功")
@recipe_bp.delete("/<int:recipe_id>")
@admin_required
def delete_recipe(recipe_id: int):
recipe = Recipe.query.get(recipe_id)
if not recipe:
return fail("食谱不存在", 404)
db.session.delete(recipe)
db.session.commit()
return ok({}, "食谱删除成功")
@recipe_bp.post("/import")
@admin_required
def import_recipes():
payload = request.get_json(silent=True) or {}
rows = payload.get("items")
if not isinstance(rows, list):
seed_file = Path(current_app.root_path).parents[0] / "seed" / "recipes_seed.json"
if seed_file.exists():
with seed_file.open("r", encoding="utf-8-sig") as file:
rows = json.load(file)
else:
return fail("导入数据为空,且未找到默认种子文件", 400)
created_count = 0
updated_count = 0
for item in rows:
name = (item.get("name") or "").strip()
if not name:
continue
recipe = Recipe.query.filter_by(name=name).first()
if recipe:
_recipe_payload(recipe, item)
updated_count += 1
else:
recipe = Recipe()
_recipe_payload(recipe, item)
db.session.add(recipe)
created_count += 1
db.session.commit()
return ok({"created": created_count, "updated": updated_count}, "食谱导入完成")