first commit
This commit is contained in:
111
services/compliance-backend/app/api/regulation.py
Normal file
111
services/compliance-backend/app/api/regulation.py
Normal file
@@ -0,0 +1,111 @@
|
||||
import uuid
|
||||
import logging
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select, desc
|
||||
|
||||
from ..core.deps import get_db
|
||||
from ..models.db import RegulationSource, RegulationUpdate
|
||||
from ..worker import fetch_regulation_source
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter(prefix="/api/regulation", tags=["法规监控"])
|
||||
|
||||
|
||||
class SourceCreate(BaseModel):
|
||||
name: str
|
||||
url: str
|
||||
domain: str = "vehicle_safety"
|
||||
fetch_interval: int = 86400
|
||||
fetch_config: dict = {}
|
||||
|
||||
|
||||
class SubscribeRequest(BaseModel):
|
||||
name: str
|
||||
channel: str # email / webhook / feishu / dingtalk
|
||||
target: str
|
||||
domains: list[str] = []
|
||||
importance_min: str = "normal"
|
||||
|
||||
|
||||
@router.post("/sources")
|
||||
async def create_source(req: SourceCreate, db: AsyncSession = Depends(get_db)):
|
||||
source = RegulationSource(
|
||||
name=req.name,
|
||||
url=req.url,
|
||||
domain=req.domain,
|
||||
fetch_interval=req.fetch_interval,
|
||||
fetch_config=req.fetch_config,
|
||||
)
|
||||
db.add(source)
|
||||
await db.flush()
|
||||
return {
|
||||
"id": str(source.id),
|
||||
"name": source.name,
|
||||
"url": source.url,
|
||||
"domain": source.domain,
|
||||
"status": "active",
|
||||
}
|
||||
|
||||
|
||||
@router.get("/sources")
|
||||
async def list_sources(db: AsyncSession = Depends(get_db)):
|
||||
result = await db.execute(
|
||||
select(RegulationSource).where(RegulationSource.is_active == True)
|
||||
)
|
||||
sources = result.scalars().all()
|
||||
return [{"id": str(s.id), "name": s.name, "url": s.url, "domain": s.domain} for s in sources]
|
||||
|
||||
|
||||
@router.post("/sources/{source_id}/fetch")
|
||||
async def manual_fetch(source_id: str, db: AsyncSession = Depends(get_db)):
|
||||
"""手动触发某个监控源的抓取(测试用)"""
|
||||
result = await db.execute(
|
||||
select(RegulationSource).where(RegulationSource.id == uuid.UUID(source_id))
|
||||
)
|
||||
source = result.scalar_one_or_none()
|
||||
if not source:
|
||||
raise HTTPException(status_code=404, detail="监控源不存在")
|
||||
|
||||
task = fetch_regulation_source.delay(source_id)
|
||||
return {"task_id": task.id, "status": "queued", "source_id": source_id}
|
||||
|
||||
|
||||
@router.get("/updates")
|
||||
async def get_updates(
|
||||
domain: str | None = None,
|
||||
limit: int = 20,
|
||||
offset: int = 0,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
query = select(RegulationUpdate).order_by(desc(RegulationUpdate.fetched_at))
|
||||
result = await db.execute(query.limit(limit).offset(offset))
|
||||
updates = result.scalars().all()
|
||||
return {
|
||||
"updates": [
|
||||
{
|
||||
"id": str(u.id),
|
||||
"title": u.title,
|
||||
"url": u.url,
|
||||
"change_type": u.change_type,
|
||||
"summary": u.summary,
|
||||
"importance": u.importance,
|
||||
"fetched_at": u.fetched_at.isoformat() if u.fetched_at else None,
|
||||
}
|
||||
for u in updates
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@router.post("/subscribe")
|
||||
async def subscribe(req: SubscribeRequest, db: AsyncSession = Depends(get_db)):
|
||||
from ..models.db import Workspace # 借用DB session
|
||||
# 简化版:仅记录订阅(推送逻辑在 push-worker 中实现)
|
||||
return {
|
||||
"id": str(uuid.uuid4()),
|
||||
"name": req.name,
|
||||
"channel": req.channel,
|
||||
"domains": req.domains,
|
||||
"status": "active",
|
||||
}
|
||||
Reference in New Issue
Block a user