Your Name e4959d584f feat: 完善代理商端业务逻辑与前后端框架
主要更新:
- 更新代理商端文档,明确项目由品牌方分配流程
- 新增Brief配置详情页(已配置)设计稿
- 完善工作台紧急待办中品牌新任务功能
- 整理Pencil设计文件中代理商端页面顺序
- 新增后端FastAPI框架及核心API
- 新增前端Next.js页面和组件库
- 添加.gitignore排除构建和缓存文件

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 19:27:31 +08:00

88 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
一致性指标 API
按达人、规则类型、时间窗口查询
"""
from datetime import datetime, timedelta, timezone
from fastapi import APIRouter, HTTPException, Query, status
from app.schemas.review import (
ConsistencyMetricsResponse,
ConsistencyWindow,
RuleConsistencyMetric,
ViolationType,
)
router = APIRouter(prefix="/metrics", tags=["metrics"])
@router.get("/consistency", response_model=ConsistencyMetricsResponse)
async def get_consistency_metrics(
influencer_id: str = Query(None, description="达人 ID必填"),
window: ConsistencyWindow = Query(ConsistencyWindow.ROLLING_30D, description="计算周期"),
rule_type: ViolationType = Query(None, description="规则类型筛选"),
) -> ConsistencyMetricsResponse:
"""
查询一致性指标
- 按达人 ID 查询
- 支持 Rolling 30 天、周度快照、月度快照
- 可按规则类型筛选
"""
# 验证必填参数
if not influencer_id:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="缺少必填参数: influencer_id",
)
# 计算时间范围
now = datetime.now(timezone.utc)
if window == ConsistencyWindow.ROLLING_30D:
period_start = now - timedelta(days=30)
period_end = now
elif window == ConsistencyWindow.SNAPSHOT_WEEK:
# 本周一到现在
days_since_monday = now.weekday()
period_start = (now - timedelta(days=days_since_monday)).replace(
hour=0, minute=0, second=0, microsecond=0
)
period_end = now
else: # SNAPSHOT_MONTH
# 本月1号到现在
period_start = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
period_end = now
# 生成模拟数据(实际应从数据库查询)
all_metrics = [
RuleConsistencyMetric(
rule_type=ViolationType.FORBIDDEN_WORD,
total_reviews=100,
violation_count=5,
violation_rate=0.05,
),
RuleConsistencyMetric(
rule_type=ViolationType.COMPETITOR_LOGO,
total_reviews=100,
violation_count=2,
violation_rate=0.02,
),
RuleConsistencyMetric(
rule_type=ViolationType.DURATION_SHORT,
total_reviews=100,
violation_count=8,
violation_rate=0.08,
),
]
# 按规则类型筛选
if rule_type:
all_metrics = [m for m in all_metrics if m.rule_type == rule_type]
return ConsistencyMetricsResponse(
influencer_id=influencer_id,
window=window,
period_start=period_start,
period_end=period_end,
metrics=all_metrics,
)