#!/bin/bash # ============================================================================= # API 文档生成脚本 # ============================================================================= # 用途: 从 FastAPI 后端自动生成 OpenAPI 规范 + 静态 HTML 文档 # 输出: # docs/api/openapi.json - OpenAPI 3.0 规范 # docs/api/index.html - Swagger UI 静态版 # docs/api/redoc.html - ReDoc 静态版 # # 用法: # bash scripts/generate-api-docs.sh # 跑后端拿 OpenAPI # bash scripts/generate-api-docs.sh --from-running # 从运行中后端拿 # bash scripts/generate-api-docs.sh --offline # 离线生成(无需后端) # ============================================================================= set -e # 颜色 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' info() { echo -e "${BLUE}[INFO]${NC} $1"; } ok() { echo -e "${GREEN}[OK]${NC} $1"; } warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; } PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$PROJECT_ROOT" API_DOCS_DIR="docs/api" mkdir -p "$API_DOCS_DIR" # 参数 MODE="auto" for arg in "$@"; do case $arg in --from-running) MODE="running" ;; --offline) MODE="offline" ;; esac done # ============================================================================= # 1. 拿 OpenAPI 规范 # ============================================================================= info "── 1/3 拿 OpenAPI 规范" case $MODE in running|auto) # 先看后端跑没 if curl -s -f http://localhost:8000/openapi.json > /tmp/openapi.json 2>/dev/null; then ok "从运行中后端拿 OpenAPI" cp /tmp/openapi.json "$API_DOCS_DIR/openapi.json" elif [ "$MODE" = "running" ]; then error "后端没跑,无法从 running 拿" else warn "后端没跑,改用离线生成" MODE="offline" fi ;; esac if [ "$MODE" = "offline" ]; then info "离线生成 OpenAPI(import FastAPI app)..." cd backend if [ ! -d "venv" ]; then warn "后端 venv 不存在,跑: python -m venv venv && pip install -r requirements.txt" fi cat > /tmp/gen_openapi.py <<'PYEOF' import json import sys try: from app.main import app spec = app.openapi() print(json.dumps(spec, ensure_ascii=False, indent=2)) except Exception as e: print(f"ERROR: {e}", file=sys.stderr) sys.exit(1) PYEOF if command -v python &> /dev/null; then if python /tmp/gen_openapi.py > "../$API_DOCS_DIR/openapi.json" 2>/dev/null; then ok "离线生成 OpenAPI 成功" else # 试 python3 if python3 /tmp/gen_openapi.py > "../$API_DOCS_DIR/openapi.json" 2>/dev/null; then ok "离线生成 OpenAPI 成功(python3)" else warn "离线生成失败,降级到 mock 模式" cat > "../$API_DOCS_DIR/openapi.json" <<'JSONEOF' { "openapi": "3.0.0", "info": { "title": "企微 IT 智能服务台 API", "version": "1.0.0", "description": "离线生成的 mock,实际跑后端再生成" }, "paths": {} } JSONEOF fi fi fi cd "$PROJECT_ROOT" fi # 验证 OpenAPI if [ ! -f "$API_DOCS_DIR/openapi.json" ]; then error "OpenAPI 规范生成失败" fi ENDPOINT_COUNT=$(python -c "import json; d=json.load(open('$API_DOCS_DIR/openapi.json')); print(len(d.get('paths', {})))" 2>/dev/null || echo "?") ok "OpenAPI 规范生成,端点数: $ENDPOINT_COUNT" # ============================================================================= # 2. 生成 Swagger UI 静态 HTML # ============================================================================= info "── 2/3 生成 Swagger UI 静态 HTML" cat > "$API_DOCS_DIR/index.html" <<'HTMLEOF'