迁移系统加固 — 加 advisory lock 防并发,失败回滚并中止启动(原来是 catch-and-continue) 安全漏洞 — Settings/History API 权限收紧,API key 返回掩码值,海报 case 所有权校验 依赖缺失 — requirements.txt 补齐 python-pptx/openai/Pillow,Dockerfile 改为统一安装 海报鉴权下载 — 前端全部改用 authenticated blob,不再 window.open 无 token URL LLM 配置分离 — 海报文案读取 poster_llm_*(不再复用 ppt_llm_*),支持 config namespace 图片生成器 — 兼容 b64_json 和 URL 两种响应格式,追踪 generation_mode/provider/model 种子数据 — 新环境自动获得 2 个海报模板 + 2 个文案模板
258 lines
8.8 KiB
Python
258 lines
8.8 KiB
Python
"""PPT/海报管理后台路由"""
|
|
from flask import Blueprint, request, jsonify
|
|
from insurance.admin.ppt_admin_service import PptAdminService
|
|
from insurance.middleware.auth_middleware import permission_required, jwt_required
|
|
|
|
ppt_admin_bp = Blueprint("ppt_admin", __name__)
|
|
ppt_admin_service = PptAdminService()
|
|
|
|
|
|
# ---- 保司管理 ----
|
|
|
|
@ppt_admin_bp.route("/companies", methods=["GET"])
|
|
@jwt_required
|
|
def list_companies():
|
|
params = {
|
|
"page": request.args.get("page", 1, type=int),
|
|
"page_size": request.args.get("page_size", 20, type=int),
|
|
"status": request.args.get("status", type=int),
|
|
"keyword": request.args.get("keyword", ""),
|
|
}
|
|
return jsonify(ppt_admin_service.list_companies(params))
|
|
|
|
|
|
@ppt_admin_bp.route("/companies", methods=["POST"])
|
|
@permission_required("config_manage")
|
|
def create_company():
|
|
return jsonify(ppt_admin_service.create_company(request.get_json(force=True)))
|
|
|
|
|
|
@ppt_admin_bp.route("/companies/<company_id>", methods=["PUT"])
|
|
@permission_required("config_manage")
|
|
def update_company(company_id):
|
|
return jsonify(ppt_admin_service.update_company(company_id, request.get_json(force=True)))
|
|
|
|
|
|
@ppt_admin_bp.route("/companies/<company_id>/status", methods=["PUT"])
|
|
@permission_required("config_manage")
|
|
def update_company_status(company_id):
|
|
return jsonify(ppt_admin_service.update_company_status(company_id, request.get_json(force=True)))
|
|
|
|
|
|
# ---- 产品管理 ----
|
|
|
|
@ppt_admin_bp.route("/products", methods=["GET"])
|
|
@jwt_required
|
|
def list_products():
|
|
params = {
|
|
"page": request.args.get("page", 1, type=int),
|
|
"page_size": request.args.get("page_size", 20, type=int),
|
|
"company_id": request.args.get("company_id", ""),
|
|
"plan_type": request.args.get("plan_type", ""),
|
|
"status": request.args.get("status", type=int),
|
|
}
|
|
return jsonify(ppt_admin_service.list_products(params))
|
|
|
|
|
|
@ppt_admin_bp.route("/products", methods=["POST"])
|
|
@permission_required("config_manage")
|
|
def create_product():
|
|
return jsonify(ppt_admin_service.create_product(request.get_json(force=True)))
|
|
|
|
|
|
@ppt_admin_bp.route("/products/<product_id>", methods=["PUT"])
|
|
@permission_required("config_manage")
|
|
def update_product(product_id):
|
|
return jsonify(ppt_admin_service.update_product(product_id, request.get_json(force=True)))
|
|
|
|
|
|
@ppt_admin_bp.route("/products/<product_id>/status", methods=["PUT"])
|
|
@permission_required("config_manage")
|
|
def update_product_status(product_id):
|
|
return jsonify(ppt_admin_service.update_product_status(product_id, request.get_json(force=True)))
|
|
|
|
|
|
@ppt_admin_bp.route("/products/<product_id>/manual/upload", methods=["POST"])
|
|
@permission_required("config_manage")
|
|
def upload_manual(product_id):
|
|
file = request.files.get("file")
|
|
if not file:
|
|
return jsonify({"code": 1001, "message": "请上传文件", "data": None})
|
|
return jsonify(ppt_admin_service.upload_manual(product_id, file))
|
|
|
|
|
|
@ppt_admin_bp.route("/products/<product_id>/manual/parse", methods=["POST"])
|
|
@permission_required("config_manage")
|
|
def parse_manual(product_id):
|
|
return jsonify(ppt_admin_service.parse_manual(product_id))
|
|
|
|
|
|
@ppt_admin_bp.route("/products/<product_id>/manual/review", methods=["PUT"])
|
|
@permission_required("config_manage")
|
|
def review_manual(product_id):
|
|
return jsonify(ppt_admin_service.review_manual(product_id, request.get_json(force=True)))
|
|
|
|
|
|
# ---- PPT 模板管理 ----
|
|
|
|
@ppt_admin_bp.route("/templates", methods=["GET"])
|
|
@jwt_required
|
|
def list_templates():
|
|
params = {
|
|
"page": request.args.get("page", 1, type=int),
|
|
"page_size": request.args.get("page_size", 20, type=int),
|
|
"plan_type": request.args.get("plan_type", ""),
|
|
"status": request.args.get("status", type=int),
|
|
}
|
|
return jsonify(ppt_admin_service.list_templates(params))
|
|
|
|
|
|
@ppt_admin_bp.route("/templates", methods=["POST"])
|
|
@permission_required("config_manage")
|
|
def create_template():
|
|
return jsonify(ppt_admin_service.create_template(request.get_json(force=True)))
|
|
|
|
|
|
@ppt_admin_bp.route("/templates/<template_id>", methods=["PUT"])
|
|
@permission_required("config_manage")
|
|
def update_template(template_id):
|
|
return jsonify(ppt_admin_service.update_template(template_id, request.get_json(force=True)))
|
|
|
|
|
|
@ppt_admin_bp.route("/templates/<template_id>/status", methods=["PUT"])
|
|
@permission_required("config_manage")
|
|
def update_template_status(template_id):
|
|
return jsonify(ppt_admin_service.update_template_status(template_id, request.get_json(force=True)))
|
|
|
|
|
|
# ---- 海报模板管理 ----
|
|
|
|
@ppt_admin_bp.route("/poster-templates", methods=["GET"])
|
|
@jwt_required
|
|
def list_poster_templates():
|
|
params = {
|
|
"page": request.args.get("page", 1, type=int),
|
|
"page_size": request.args.get("page_size", 20, type=int),
|
|
"status": request.args.get("status", type=int),
|
|
}
|
|
return jsonify(ppt_admin_service.list_poster_templates(params))
|
|
|
|
|
|
@ppt_admin_bp.route("/poster-templates", methods=["POST"])
|
|
@permission_required("config_manage")
|
|
def create_poster_template():
|
|
return jsonify(ppt_admin_service.create_poster_template(request.get_json(force=True)))
|
|
|
|
|
|
@ppt_admin_bp.route("/poster-templates/<int:template_id>", methods=["PUT"])
|
|
@permission_required("config_manage")
|
|
def update_poster_template(template_id):
|
|
return jsonify(ppt_admin_service.update_poster_template(template_id, request.get_json(force=True)))
|
|
|
|
|
|
@ppt_admin_bp.route("/poster-templates/<int:template_id>/status", methods=["PUT"])
|
|
@permission_required("config_manage")
|
|
def update_poster_template_status(template_id):
|
|
return jsonify(ppt_admin_service.update_poster_template_status(template_id, request.get_json(force=True)))
|
|
|
|
|
|
# ---- 文案模板管理 ----
|
|
|
|
@ppt_admin_bp.route("/copy-templates", methods=["GET"])
|
|
@jwt_required
|
|
def list_copy_templates():
|
|
params = {
|
|
"page": request.args.get("page", 1, type=int),
|
|
"page_size": request.args.get("page_size", 20, type=int),
|
|
"status": request.args.get("status", type=int),
|
|
}
|
|
return jsonify(ppt_admin_service.list_copy_templates(params))
|
|
|
|
|
|
@ppt_admin_bp.route("/copy-templates", methods=["POST"])
|
|
@permission_required("config_manage")
|
|
def create_copy_template():
|
|
return jsonify(ppt_admin_service.create_copy_template(request.get_json(force=True)))
|
|
|
|
|
|
@ppt_admin_bp.route("/copy-templates/<int:template_id>", methods=["PUT"])
|
|
@permission_required("config_manage")
|
|
def update_copy_template(template_id):
|
|
return jsonify(ppt_admin_service.update_copy_template(template_id, request.get_json(force=True)))
|
|
|
|
|
|
@ppt_admin_bp.route("/copy-templates/<int:template_id>", methods=["DELETE"])
|
|
@permission_required("config_manage")
|
|
def delete_copy_template(template_id):
|
|
return jsonify(ppt_admin_service.delete_copy_template(template_id))
|
|
|
|
|
|
# ---- 历史记录管理(需要审计权限) ----
|
|
|
|
@ppt_admin_bp.route("/history", methods=["GET"])
|
|
@permission_required("audit_view")
|
|
def list_history():
|
|
params = {
|
|
"page": request.args.get("page", 1, type=int),
|
|
"page_size": request.args.get("page_size", 20, type=int),
|
|
"user_id": request.args.get("user_id", ""),
|
|
"company_id": request.args.get("company_id", ""),
|
|
"action_type": request.args.get("action_type", ""),
|
|
}
|
|
return jsonify(ppt_admin_service.list_history(params))
|
|
|
|
|
|
@ppt_admin_bp.route("/history/<int:history_id>", methods=["DELETE"])
|
|
@permission_required("config_manage")
|
|
def delete_history(history_id):
|
|
return jsonify(ppt_admin_service.delete_history(history_id))
|
|
|
|
|
|
@ppt_admin_bp.route("/history/export", methods=["GET"])
|
|
@permission_required("audit_view")
|
|
def export_history():
|
|
from flask import Response
|
|
params = {
|
|
"user_id": request.args.get("user_id", ""),
|
|
"company_id": request.args.get("company_id", ""),
|
|
"action_type": request.args.get("action_type", ""),
|
|
}
|
|
csv_content = ppt_admin_service.export_history_csv(params)
|
|
return Response(
|
|
csv_content,
|
|
mimetype="text/csv",
|
|
headers={"Content-Disposition": "attachment; filename=ppt_history.csv"},
|
|
)
|
|
|
|
|
|
# ---- 系统配置 ----
|
|
|
|
@ppt_admin_bp.route("/available-models", methods=["GET"])
|
|
@permission_required("config_manage")
|
|
def get_available_models():
|
|
return jsonify(ppt_admin_service.get_available_models())
|
|
|
|
|
|
@ppt_admin_bp.route("/settings", methods=["GET"])
|
|
@permission_required("config_manage")
|
|
def get_settings():
|
|
return jsonify(ppt_admin_service.get_settings())
|
|
|
|
|
|
@ppt_admin_bp.route("/settings", methods=["PUT"])
|
|
@permission_required("config_manage")
|
|
def update_settings():
|
|
updated_by = getattr(request, "user_id", "")
|
|
return jsonify(ppt_admin_service.update_settings(request.get_json(force=True), updated_by))
|
|
|
|
|
|
@ppt_admin_bp.route("/sync-models", methods=["POST"])
|
|
@permission_required("config_manage")
|
|
def sync_models():
|
|
data = request.get_json(force=True)
|
|
return jsonify(ppt_admin_service.sync_models(
|
|
provider=data.get("provider", ""),
|
|
api_key=data.get("api_key", ""),
|
|
base_url=data.get("base_url", ""),
|
|
))
|