feat: 内容数据迁移至数据库,合规审查全链路打通

- 文章 HTML 存储从文件系统迁移至 articles 表,删除 releases 目录
- 合规审查从 DB 读取 HTML,审查结果写回 DB,通过后自动推进至待发布
- 新增 todayCount 筛选按钮,与系统概览统计数据一致
- 全屏预览修复:提升 z-index 超过侧边栏,添加退出全屏/关闭按钮
- 统一 '优化' → '审查' 命名,消除前后端术语不一致
- 调度器创作完成后自动触发审查(生成 → 审查 → 待发布)
- 清理旧备份/调试文件、过期大纲和研究笔记
This commit is contained in:
Yuzhiran Dev
2026-05-13 17:33:56 +08:00
parent bc6a302e59
commit 233e23016c
234 changed files with 5670 additions and 10651 deletions
+136 -3
View File
@@ -80,11 +80,50 @@ def update_topic_status(topic_id: str, status: str, db: Optional[Session] = None
if close_db:
db.close()
def get_active_llm_config(db: Optional[Session] = None) -> Optional[Dict]:
"""获取启用的 LLM 配置,优先读取 system_configs 中的 review_llm_id
返回格式: { "model", "temperature", "max_tokens", "system_prompt", "name" }
无配置时返回 None(调用方应使用环境变量默认值)
"""
close_db = False
if db is None:
db = SessionLocal()
close_db = True
try:
from app.models import LLMConfig, SystemConfig
# 先查系统配置中指定的 review_llm_id
sc = db.query(SystemConfig).filter(SystemConfig.key == 'review_llm_id').first()
target_id = None
if sc and sc.value and sc.value.isdigit():
target_id = int(sc.value)
query = db.query(LLMConfig)
if target_id:
query = query.filter(LLMConfig.id == target_id)
query = query.filter(LLMConfig.is_active == True)
cfg = query.first()
if not cfg:
cfg = db.query(LLMConfig).filter(LLMConfig.is_active == True).first()
if cfg:
return {
"id": cfg.id,
"name": cfg.name,
"model": cfg.model,
"temperature": cfg.temperature,
"max_tokens": cfg.max_tokens,
"system_prompt": cfg.system_prompt,
"user_prompt_template": cfg.user_prompt_template,
}
return None
finally:
if close_db:
db.close()
def topic_to_dict(topic: Topic) -> Dict:
return {
'id': topic.id,
'title': topic.title,
'field': topic.field.name if topic.field else None,
'field': topic.field_name,
'format': topic.format,
'core_concept': topic.core_concept,
'audience_pain': topic.audience_pain,
@@ -131,7 +170,7 @@ def save_topics_to_db(topics_data: List[Dict]):
existing = db.query(Topic).filter(Topic.id == t['id']).first()
if existing:
# 更新字段
for field in ['title', 'field', 'format', 'core_concept', 'audience_pain', 'unique_angle', 'priority', 'priority_score', 'total_score', 'status', 'cases', 'source_file', 'compliance_score', 'platform_urls']:
for field in ['title', 'field_name', 'format', 'core_concept', 'audience_pain', 'unique_angle', 'priority', 'priority_score', 'total_score', 'status', 'cases', 'source_file', 'compliance_score', 'platform_urls']:
setattr(existing, field, t.get(field, getattr(existing, field)))
if t.get('ready_at'):
try:
@@ -148,7 +187,7 @@ def save_topics_to_db(topics_data: List[Dict]):
new_topic = Topic(
id=t['id'],
title=t['title'],
field=t.get('field', '可持续生活系统'),
field_name=t.get('field_name') or t.get('field', '可持续生活系统'),
format=t.get('format'),
core_concept=t.get('core_concept'),
audience_pain=t.get('audience_pain'),
@@ -173,3 +212,97 @@ def save_topics_to_db(topics_data: List[Dict]):
raise
finally:
db.close()
def save_article(topic_id: str, platform: str, html_content: str, db: Optional[Session] = None) -> Dict:
"""保存/更新文章到 articles 表"""
close_db = False
if db is None:
db = SessionLocal()
close_db = True
try:
from app.models import Article
article_id = f"{platform}_{topic_id}"
existing = db.query(Article).filter(Article.id == article_id).first()
now = datetime.now()
if existing:
existing.html_content = html_content
existing.compliance_score = existing.compliance_score
else:
article = Article(
id=article_id,
topic_id=topic_id,
platform=platform,
file_path=f"db:{article_id}",
html_content=html_content,
status="draft",
compliance_score=None
)
db.add(article)
db.commit()
return {"id": article_id, "topic_id": topic_id, "platform": platform}
except Exception:
db.rollback()
raise
finally:
if close_db:
db.close()
def get_article(topic_id: str, platform: str, db: Optional[Session] = None) -> Optional[Dict]:
"""从 articles 表获取文章 HTML"""
close_db = False
if db is None:
db = SessionLocal()
close_db = True
try:
from app.models import Article
article_id = f"{platform}_{topic_id}"
article = db.query(Article).filter(Article.id == article_id).first()
if not article:
return None
return {
"id": article.id,
"topic_id": article.topic_id,
"platform": article.platform,
"html_content": article.html_content,
"status": article.status,
"compliance_score": article.compliance_score,
"created_at": article.created_at.isoformat() if article.created_at else None,
}
finally:
if close_db:
db.close()
def get_articles_by_topic(topic_id: str, db: Optional[Session] = None) -> List[Dict]:
"""获取某选题在所有平台的文章"""
close_db = False
if db is None:
db = SessionLocal()
close_db = True
try:
from app.models import Article
articles = db.query(Article).filter(Article.topic_id == topic_id).all()
return [{
"id": a.id,
"topic_id": a.topic_id,
"platform": a.platform,
"html_content": a.html_content,
"status": a.status,
"compliance_score": a.compliance_score,
} for a in articles]
finally:
if close_db:
db.close()
def delete_articles_by_topic(topic_id: str, db: Optional[Session] = None):
"""删除某选题的所有文章"""
close_db = False
if db is None:
db = SessionLocal()
close_db = True
try:
from app.models import Article
db.query(Article).filter(Article.topic_id == topic_id).delete()
db.commit()
finally:
if close_db:
db.close()