feat: 内容数据迁移至数据库,合规审查全链路打通
- 文章 HTML 存储从文件系统迁移至 articles 表,删除 releases 目录 - 合规审查从 DB 读取 HTML,审查结果写回 DB,通过后自动推进至待发布 - 新增 todayCount 筛选按钮,与系统概览统计数据一致 - 全屏预览修复:提升 z-index 超过侧边栏,添加退出全屏/关闭按钮 - 统一 '优化' → '审查' 命名,消除前后端术语不一致 - 调度器创作完成后自动触发审查(生成 → 审查 → 待发布) - 清理旧备份/调试文件、过期大纲和研究笔记
This commit is contained in:
@@ -1,20 +1,10 @@
|
||||
import json
|
||||
from datetime import datetime, date
|
||||
from pathlib import Path
|
||||
from sqlalchemy.orm import Session
|
||||
from ..database import SessionLocal
|
||||
from ..models import Topic
|
||||
import os
|
||||
|
||||
# 计算项目根目录(从本文件位置上升4层)
|
||||
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
||||
if os.getenv('PROJECT_ROOT'):
|
||||
PROJECT_ROOT = Path(os.getenv('PROJECT_ROOT'))
|
||||
TOPICS_FILE = PROJECT_ROOT / "automation" / "data" / "sustainability_topics.json"
|
||||
|
||||
def sync_topic_to_db(topic_id: str, db: Session = None) -> Topic:
|
||||
"""注意:此函数原用于将JSON单个选题同步到数据库。现已不需要,保留用于兼容。当前方向相反(DB为主),此处仅从数据库导出到JSON(如果需要)"""
|
||||
# 为了不破坏旧调用,我们改为从数据库读取并写入 JSON 文件(单条更新)
|
||||
close_db = False
|
||||
if db is None:
|
||||
db = SessionLocal()
|
||||
@@ -23,88 +13,24 @@ def sync_topic_to_db(topic_id: str, db: Session = None) -> Topic:
|
||||
topic = db.query(Topic).filter(Topic.id == topic_id).first()
|
||||
if not topic:
|
||||
raise ValueError(f"Topic {topic_id} not found in DB")
|
||||
# 写入 JSON 文件(作为备份)
|
||||
try:
|
||||
if TOPICS_FILE.exists():
|
||||
with open(TOPICS_FILE, 'r', encoding='utf-8') as f:
|
||||
topics = json.load(f)
|
||||
else:
|
||||
topics = []
|
||||
# 转为字典
|
||||
tdict = {
|
||||
'id': topic.id,
|
||||
'title': topic.title,
|
||||
'field': topic.field,
|
||||
'format': topic.format,
|
||||
'core_concept': topic.core_concept,
|
||||
'audience_pain': topic.audience_pain,
|
||||
'unique_angle': topic.unique_angle,
|
||||
'priority': topic.priority,
|
||||
'priority_score': topic.priority_score,
|
||||
'total_score': topic.total_score,
|
||||
'status': topic.status,
|
||||
'cases': topic.cases or [],
|
||||
'source_file': topic.source_file,
|
||||
'created_at': topic.created_at.isoformat() if topic.created_at else None,
|
||||
'updated_at': topic.updated_at.isoformat() if topic.updated_at else None,
|
||||
'ready_at': topic.ready_at.isoformat() if topic.ready_at else None,
|
||||
'published_at': topic.published_at.isoformat() if topic.published_at else None,
|
||||
'compliance_score': topic.compliance_score,
|
||||
'platform_urls': topic.platform_urls or {}
|
||||
}
|
||||
# 更新或追加
|
||||
found = False
|
||||
for i, t in enumerate(topics):
|
||||
if t['id'] == topic_id:
|
||||
topics[i] = tdict
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
topics.append(tdict)
|
||||
with open(TOPICS_FILE, 'w', encoding='utf-8') as f:
|
||||
json.dump(topics, f, ensure_ascii=False, indent=2)
|
||||
except Exception as e:
|
||||
print(f"[Warning] JSON backup failed: {e}")
|
||||
return topic
|
||||
finally:
|
||||
if close_db:
|
||||
db.close()
|
||||
|
||||
def sync_all_topics():
|
||||
"""导出所有选题到 JSON 文件(用于备份或兼容)"""
|
||||
db = SessionLocal()
|
||||
logger = __import__('logging').getLogger(__name__)
|
||||
try:
|
||||
topics = db.query(Topic).order_by(Topic.created_at).all()
|
||||
topic_list = []
|
||||
for t in topics:
|
||||
tdict = {
|
||||
'id': t.id,
|
||||
'title': t.title,
|
||||
'field': t.field,
|
||||
'format': t.format,
|
||||
'core_concept': t.core_concept,
|
||||
'audience_pain': t.audience_pain,
|
||||
'unique_angle': t.unique_angle,
|
||||
'priority': t.priority,
|
||||
'priority_score': t.priority_score,
|
||||
'total_score': t.total_score,
|
||||
'status': t.status,
|
||||
'cases': t.cases or [],
|
||||
'source_file': t.source_file,
|
||||
'created_at': t.created_at.isoformat() if t.created_at else None,
|
||||
'updated_at': t.updated_at.isoformat() if t.updated_at else None,
|
||||
'ready_at': t.ready_at.isoformat() if t.ready_at else None,
|
||||
'published_at': t.published_at.isoformat() if t.published_at else None,
|
||||
'compliance_score': t.compliance_score,
|
||||
'platform_urls': t.platform_urls or {}
|
||||
}
|
||||
topic_list.append(tdict)
|
||||
TOPICS_FILE.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(TOPICS_FILE, 'w', encoding='utf-8') as f:
|
||||
json.dump(topic_list, f, ensure_ascii=False, indent=2)
|
||||
print(f"✅ 导出 {len(topic_list)} 个选题到 JSON (兼容模式)")
|
||||
finally:
|
||||
from sqlalchemy import func
|
||||
db = SessionLocal()
|
||||
total = db.query(Topic).count()
|
||||
rows = db.query(Topic.status, func.count(Topic.id)).group_by(Topic.status).all()
|
||||
by_status = {s: int(c) for s, c in rows}
|
||||
logger.info(f"sync_all_topics: DB verified — {total} topics total, statuses: {by_status}")
|
||||
db.close()
|
||||
except Exception as e:
|
||||
logger.error(f"sync_all_topics: DB connection failed — {e}")
|
||||
raise
|
||||
|
||||
if __name__ == "__main__":
|
||||
sync_all_topics()
|
||||
|
||||
Reference in New Issue
Block a user