配置全面迁移数据库:PromptConfig、TaskConfig动态调度、敏感词/清洗规则/趋势映射/平台标签/痛点模板全部可编辑
- 新增 PromptConfig 模型 + API,支持提示词在线编辑(16条默认) - 调度器动态读取 TaskConfig.schedule,admin 可调执行时间 - 新增 KeywordDomainMap、SensitiveWord、ContentCleanRule、TrendFieldMapping 表 - DOMAINS、TREND_DOMAIN_MAP、PLATFORM_TAGS、china_pains、RSS关键词、priority_weights 全部迁移到 DB - tasks.html 重构:卡片网格+配置/产出/历史/提示词四个Tab,折叠显示 - 清理冗余代码:DEFAULT_PROMPTS死代码、collector.py unreachable代码、compliance_checker bug - strip_thinking_html 改用 DB 规则优先
This commit is contained in:
@@ -9,7 +9,7 @@ from typing import Dict, Any, List, Optional
|
||||
import os
|
||||
import json
|
||||
from ..database import get_db
|
||||
from ..models import Topic, Article
|
||||
from ..models import Topic, Article, TaskConfig, TaskLog
|
||||
from ..core.generator import run_creator, get_generator_status
|
||||
from ..core.optimizer import run_optimizer, get_optimizer_status
|
||||
from ..core.collector import run_collector, get_collector_status
|
||||
@@ -61,7 +61,7 @@ def get_status(db: Session = Depends(get_db)):
|
||||
}
|
||||
|
||||
@router.post("/generate/run", dependencies=[Depends(get_current_user)])
|
||||
def trigger_generation(topic_id: str = Body(None, embed=True), db: Session = Depends(get_db), current_user=Depends(get_current_user)):
|
||||
def trigger_generation(topic_id: Optional[str] = None, db: Session = Depends(get_db), current_user=Depends(get_current_user)):
|
||||
logger.info(f"Generation triggered by {current_user.username}, topic_id={topic_id}")
|
||||
try:
|
||||
result = run_creator(topic_id)
|
||||
@@ -93,7 +93,7 @@ def collection_status():
|
||||
return status
|
||||
|
||||
@router.post("/review/run", dependencies=[Depends(get_current_user)])
|
||||
def trigger_review(topic_ids: List[str] = Body(None, embed=True), db: Session = Depends(get_db), current_user=Depends(get_current_user)):
|
||||
def trigger_review(topic_ids: Optional[List[str]] = None, db: Session = Depends(get_db), current_user=Depends(get_current_user)):
|
||||
try:
|
||||
result = run_optimizer(topic_ids)
|
||||
return {"message": "合规审查已后台启动", "pid": result.get("pid")}
|
||||
@@ -247,47 +247,61 @@ def get_scheduler_status():
|
||||
|
||||
|
||||
@router.get("/modules/status", dependencies=[Depends(get_current_user)])
|
||||
def get_modules_status():
|
||||
today_str = date.today().isoformat()
|
||||
log_based: dict = {
|
||||
"scheduled_collect": {"name": "📡 内容采集", "log": LOGS_DIR / f"collector_{today_str}.log"},
|
||||
"scheduled_refresh_search_cache": {"name": "🔍 搜索缓存", "log": LOGS_DIR / f"opencode_search_{today_str}.log"},
|
||||
"scheduled_fetch_trends": {"name": "🔥 热点趋势", "log": LOGS_DIR / f"trends_{today_str}.log"},
|
||||
"scheduled_generate": {"name": "🤖 内容创作", "log": LOGS_DIR / f"creator_{today_str}.log"},
|
||||
"scheduled_optimize": {"name": "🔍 合规审查", "log": LOGS_DIR / f"optimizer_{today_str}.log"},
|
||||
"scheduled_optimize_sources": {"name": "📡 信息源优化", "log": LOGS_DIR / f"optimizer_sources_{today_str}.log"},
|
||||
"scheduled_metrics_sync": {"name": "📊 指标同步", "log": LOGS_DIR / f"metrics_sync_{today_str}.log"},
|
||||
def get_modules_status(db: Session = Depends(get_db)):
|
||||
configs = db.query(TaskConfig).all()
|
||||
config_map = {c.module_id: c for c in configs}
|
||||
|
||||
MODULE_META = {
|
||||
"scheduled_refresh_search_cache": {"name": "🔍 搜索缓存", "cron": "01:00", "params_desc": {"refresh_queries": "搜索关键词列表"}},
|
||||
"scheduled_fetch_trends": {"name": "🔥 热点趋势", "cron": "01:10", "params_desc": {}},
|
||||
"scheduled_collect": {"name": "📡 内容采集", "cron": "01:30", "params_desc": {"max_topics": "最大选题数", "categories": "采集类别"}},
|
||||
"scheduled_generate": {"name": "🤖 内容创作", "cron": "02:00", "params_desc": {"auto_review": "自动合规审查"}},
|
||||
"scheduled_optimize": {"name": "🔍 合规审查", "cron": "03:00", "params_desc": {"auto_pass_threshold": "自动通过分数阈值"}},
|
||||
"scheduled_optimize_sources": {"name": "📡 信息源优化", "cron": "05:00", "params_desc": {}},
|
||||
"scheduled_metrics_sync": {"name": "📊 指标同步", "cron": "06:00", "params_desc": {}},
|
||||
}
|
||||
jobs = {j['id']: j for j in scheduler.get_jobs()}
|
||||
|
||||
modules = []
|
||||
for mod_id, cfg in log_based.items():
|
||||
log_file = cfg["log"]
|
||||
last_run = None
|
||||
task_count = 0
|
||||
success_rate = None
|
||||
if log_file.exists():
|
||||
mtime = datetime.fromtimestamp(log_file.stat().st_mtime)
|
||||
last_run = mtime.strftime("%Y-%m-%d %H:%M")
|
||||
content = log_file.read_text(encoding="utf-8", errors="ignore")
|
||||
task_count = content.count("完成") + content.count("success") + content.count("SUCCESS")
|
||||
total = task_count + content.count("失败") + content.count("failed") + content.count("ERROR")
|
||||
success_rate = round(task_count / total * 100) if total > 0 else None
|
||||
status = "running" if mod_id in jobs else "stopped"
|
||||
job = jobs.get(mod_id)
|
||||
next_run = None
|
||||
if job and job.get("next_run_time"):
|
||||
try:
|
||||
next_dt = datetime.fromisoformat(job["next_run_time"])
|
||||
next_run = next_dt.strftime("%Y-%m-%d %H:%M")
|
||||
except Exception:
|
||||
next_run = job["next_run_time"]
|
||||
for mod_id, meta in MODULE_META.items():
|
||||
cfg = config_map.get(mod_id)
|
||||
latest = db.query(TaskLog).filter(TaskLog.module_id == mod_id).order_by(TaskLog.started_at.desc()).first()
|
||||
next_run = _get_next_run(mod_id)
|
||||
|
||||
total = db.query(TaskLog).filter(TaskLog.module_id == mod_id).count()
|
||||
success = db.query(TaskLog).filter(TaskLog.module_id == mod_id, TaskLog.status == "success").count()
|
||||
failed = db.query(TaskLog).filter(TaskLog.module_id == mod_id, TaskLog.status == "failed").count()
|
||||
running = db.query(TaskLog).filter(TaskLog.module_id == mod_id, TaskLog.status == "running").count()
|
||||
|
||||
modules.append({
|
||||
"id": mod_id,
|
||||
"title": cfg["name"],
|
||||
"status": status,
|
||||
"last_run": last_run or "从未运行",
|
||||
"next_run": next_run or "待计划",
|
||||
"task_count": task_count,
|
||||
"success_rate": success_rate if success_rate is not None else 0,
|
||||
"module_id": mod_id,
|
||||
"title": meta["name"],
|
||||
"enabled": cfg.enabled if cfg else True,
|
||||
"params": cfg.params if cfg else {},
|
||||
"params_desc": meta["params_desc"],
|
||||
"schedule": cfg.schedule if cfg else meta["cron"],
|
||||
"cron_default": meta["cron"],
|
||||
"status": "running" if running else ("stopped" if not (cfg and cfg.enabled) else "idle"),
|
||||
"last_run": latest.started_at.strftime("%Y-%m-%d %H:%M") if latest and latest.started_at else None,
|
||||
"last_status": latest.status if latest else None,
|
||||
"last_message": latest.message if latest else None,
|
||||
"last_result": latest.result_data if latest else None,
|
||||
"next_run": next_run,
|
||||
"total_runs": total,
|
||||
"success_runs": success,
|
||||
"failed_runs": failed,
|
||||
"running": running,
|
||||
})
|
||||
return {"modules": modules, "scheduler": {"running": scheduler._started, "jobs": scheduler.get_jobs()}}
|
||||
|
||||
jobs = scheduler.get_jobs()
|
||||
return {"modules": modules, "scheduler": {"running": scheduler._started, "jobs": jobs}}
|
||||
|
||||
|
||||
def _get_next_run(mod_id: str) -> Optional[str]:
|
||||
for job in scheduler.get_jobs():
|
||||
if job["id"] == mod_id and job["next_run_time"]:
|
||||
try:
|
||||
dt = datetime.fromisoformat(job["next_run_time"])
|
||||
return dt.strftime("%Y-%m-%d %H:%M")
|
||||
except Exception:
|
||||
return job["next_run_time"]
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user