""" OKR模板库 API — 按维度筛选 + 用户自定义模板 """ from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from typing import Optional from app.database import get_db from app.auth_middleware import require_role from app.models import OKRTemplate router = APIRouter(prefix="/api/cma/okr-templates", tags=["OKR模板库"], dependencies=[Depends(require_role("ceo", "finance", "it"))], ) @router.get("") def list_okr_templates( dimension: Optional[str] = Query(None, description="按维度筛选: finance/customer/process/learning"), source: Optional[str] = Query(None, description="按来源筛选: system/user/industry_pack"), industry_tag: Optional[str] = Query(None, description="按行业标签筛选"), active_only: bool = Query(True, description="仅返回启用模板"), db: Session = Depends(get_db), ): """列出 OKR 模板,支持按维度筛选""" q = db.query(OKRTemplate) if dimension: q = q.filter(OKRTemplate.dimension == dimension) if source: q = q.filter(OKRTemplate.source == source) if industry_tag: q = q.filter(OKRTemplate.industry_tag == industry_tag) if active_only: q = q.filter(OKRTemplate.is_active == 1) templates = q.order_by(OKRTemplate.sort_order, OKRTemplate.id).all() return { "total": len(templates), "items": [ { "id": t.id, "name": t.name, "description": t.description, "dimension": t.dimension, "layer": t.layer, "industry_tag": t.industry_tag, "preset_krs": t.preset_krs, "source": t.source, "use_count": t.use_count, "sort_order": t.sort_order, "is_active": t.is_active, "created_at": t.created_at.isoformat() if t.created_at else None, } for t in templates ], } @router.get("/{template_id}") def get_okr_template(template_id: int, db: Session = Depends(get_db)): """获取单个 OKR 模板详情""" t = db.query(OKRTemplate).filter(OKRTemplate.id == template_id).first() if not t: raise HTTPException(404, "模板不存在") return { "id": t.id, "name": t.name, "description": t.description, "dimension": t.dimension, "layer": t.layer, "industry_tag": t.industry_tag, "preset_krs": t.preset_krs, "source": t.source, "use_count": t.use_count, "sort_order": t.sort_order, "is_active": t.is_active, } @router.post("") def create_okr_template(data: dict, db: Session = Depends(get_db)): """用户自定义 OKR 模板""" name = data.get("name", "").strip() if not name: raise HTTPException(400, "模板名称不能为空") dimension = data.get("dimension", "") if dimension not in ("finance", "customer", "process", "learning"): raise HTTPException(400, "维度无效,必须是 finance/customer/process/learning") preset_krs = data.get("preset_krs", []) if not isinstance(preset_krs, list) or len(preset_krs) == 0: raise HTTPException(400, "至少需要一个预设KR") t = OKRTemplate( name=name, description=data.get("description", ""), dimension=dimension, layer=data.get("layer", "level3"), industry_tag=data.get("industry_tag", "general"), preset_krs=preset_krs, source="user", sort_order=data.get("sort_order", 0), ) db.add(t) db.commit() db.refresh(t) return {"ok": True, "id": t.id, "name": t.name} @router.post("/{template_id}/use") def increment_use_count(template_id: int, db: Session = Depends(get_db)): """增加模板使用次数""" t = db.query(OKRTemplate).filter(OKRTemplate.id == template_id).first() if not t: raise HTTPException(404, "模板不存在") t.use_count = (t.use_count or 0) + 1 db.commit() return {"ok": True, "use_count": t.use_count}