2025-11-28 17:39:54 +08:00

116 lines
3.9 KiB
Python

import threading
from flask import Blueprint, flash, redirect, render_template, request, url_for, current_app
from flask_login import current_user, login_required
from app.extensions import db, scheduler
from app.forms import ApiConfigForm
from app.models import ApiConfig
from app.services.api_executor import execute_api_by_id
from app.services.scheduler import SchedulerService
apis_bp = Blueprint("apis", __name__, url_prefix="/apis")
def _scheduler_service() -> SchedulerService:
return SchedulerService(scheduler)
@apis_bp.route("", methods=["GET"])
@login_required
def list_apis():
name = request.args.get("name")
enabled = request.args.get("enabled")
query = ApiConfig.query
if name:
query = query.filter(ApiConfig.name.ilike(f"%{name}%"))
if enabled in {"0", "1"}:
query = query.filter(ApiConfig.enabled == (enabled == "1"))
apis = query.order_by(ApiConfig.updated_at.desc()).all()
return render_template("apis/list.html", apis=apis)
@apis_bp.route("/new", methods=["GET", "POST"])
@login_required
def create_api():
form = ApiConfigForm()
if form.validate_on_submit():
api = ApiConfig(
name=form.name.data,
description=form.description.data,
url=form.url.data,
http_method=form.http_method.data,
headers=form.headers.data,
query_params=form.query_params.data,
body=form.body.data,
schedule_type=form.schedule_type.data,
schedule_expression=form.schedule_expression.data,
timeout_seconds=form.timeout_seconds.data,
retry_times=form.retry_times.data,
retry_interval_seconds=form.retry_interval_seconds.data,
enabled=form.enabled.data,
created_by=current_user.id,
)
db.session.add(api)
db.session.commit()
if api.enabled:
_scheduler_service().add_job_for_api(api)
flash("API 配置已创建", "success")
return redirect(url_for("apis.list_apis"))
return render_template("apis/form.html", form=form, api=None)
@apis_bp.route("/<int:api_id>/edit", methods=["GET", "POST"])
@login_required
def edit_api(api_id: int):
api = ApiConfig.query.get_or_404(api_id)
form = ApiConfigForm(obj=api)
if form.validate_on_submit():
form.populate_obj(api)
db.session.commit()
if api.enabled:
_scheduler_service().reschedule_job_for_api(api)
else:
_scheduler_service().remove_job_for_api(api.id)
flash("API 配置已更新", "success")
return redirect(url_for("apis.list_apis"))
return render_template("apis/form.html", form=form, api=api)
@apis_bp.route("/<int:api_id>/toggle", methods=["POST"])
@login_required
def toggle_api(api_id: int):
api = ApiConfig.query.get_or_404(api_id)
api.enabled = not api.enabled
db.session.commit()
svc = _scheduler_service()
if api.enabled:
svc.add_job_for_api(api)
flash("API 已启用并加入调度", "success")
else:
svc.remove_job_for_api(api.id)
flash("API 已停用并移除调度", "info")
return redirect(url_for("apis.list_apis"))
@apis_bp.route("/<int:api_id>/delete", methods=["POST"])
@login_required
def delete_api(api_id: int):
api = ApiConfig.query.get_or_404(api_id)
db.session.delete(api)
db.session.commit()
_scheduler_service().remove_job_for_api(api_id)
flash("API 配置已删除", "info")
return redirect(url_for("apis.list_apis"))
@apis_bp.route("/<int:api_id>/run", methods=["POST"])
@login_required
def run_now(api_id: int):
api = ApiConfig.query.get_or_404(api_id)
app_obj = current_app._get_current_object()
threading.Thread(target=execute_api_by_id, args=(api.id, app_obj), daemon=True).start()
flash("已触发立即执行,稍后在日志中查看结果。", "success")
return redirect(url_for("apis.list_apis"))