feat: Phase 4 多租户隔离 + 四阶段升级测试 + CSS 统一化
Phase 4: org_id 注入 JWT/API 过滤/组织管理 CRUD/前端组织列 测试: tests/test_phase_upgrades.py 97项全覆盖 CSS: theme-modern.css 共享 mobile-card-list/status-dot/search-bar 等模式 修复: initial_data.py LLM配置 NOT NULL 约束, TopicResponse 含 org_id
This commit is contained in:
@@ -8,6 +8,7 @@ import os
|
||||
import sys
|
||||
import json
|
||||
import datetime
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Tuple, Optional
|
||||
from dataclasses import dataclass
|
||||
@@ -25,6 +26,13 @@ import random
|
||||
# 确保项目根目录在路径中
|
||||
PROJECT_ROOT = Path('/root/openclaw-workspace/projects/yu-zhi-ran')
|
||||
sys.path.insert(0, str(PROJECT_ROOT))
|
||||
sys.path.insert(0, str(PROJECT_ROOT / 'platform' / 'backend'))
|
||||
|
||||
from db_helper import get_topic_by_id
|
||||
from app.models import Article
|
||||
from app.database import SessionLocal
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# 加载配置
|
||||
CONFIG_DIR = PROJECT_ROOT / "config"
|
||||
@@ -441,7 +449,85 @@ class ImageGenerator:
|
||||
|
||||
return files
|
||||
|
||||
def generate_for_topic(topic_id: str, platforms: List[str] = None) -> Dict[str, Dict[str, str]]:
|
||||
"""为指定选题生成三平台配图,路径存入 articles 表"""
|
||||
if platforms is None:
|
||||
platforms = ["zhihu", "wechat", "xiaohongshu"]
|
||||
|
||||
topic = get_topic_by_id(topic_id)
|
||||
if not topic:
|
||||
raise ValueError(f"Topic {topic_id} not found")
|
||||
|
||||
title = topic.get("title", "无标题")
|
||||
generator = ImageGenerator()
|
||||
results = {}
|
||||
|
||||
for platform in platforms:
|
||||
try:
|
||||
files = generator.generate_all_placeholders(title, platform)
|
||||
cover_path = str(files.get("cover", ""))
|
||||
chart_path = str(files.get("data_chart", ""))
|
||||
checklist_path = str(files.get("action_checklist", ""))
|
||||
|
||||
images = {
|
||||
"cover": cover_path,
|
||||
"chart": chart_path,
|
||||
"checklist": checklist_path,
|
||||
}
|
||||
|
||||
# 存入 DB
|
||||
save_article_images(topic_id, platform, images)
|
||||
|
||||
results[platform] = images
|
||||
logger.info(f" [{platform}] cover={Path(cover_path).name}" if cover_path else "")
|
||||
except Exception as e:
|
||||
logger.error(f" [{platform}] 生成失败: {e}")
|
||||
results[platform] = {}
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def save_article_images(topic_id: str, platform: str, images: Dict[str, str]):
|
||||
"""将图片路径写入 articles 表的 images 字段"""
|
||||
db = SessionLocal()
|
||||
try:
|
||||
from app.models import Article
|
||||
article_id = f"{platform}_{topic_id}"
|
||||
article = db.query(Article).filter(Article.id == article_id).first()
|
||||
if article:
|
||||
existing = article.images or {}
|
||||
existing.update(images)
|
||||
article.images = existing
|
||||
else:
|
||||
article = Article(
|
||||
id=article_id,
|
||||
topic_id=topic_id,
|
||||
platform=platform,
|
||||
file_path=f"db:{article_id}",
|
||||
status="draft",
|
||||
images=images,
|
||||
)
|
||||
db.add(article)
|
||||
db.commit()
|
||||
except Exception:
|
||||
db.rollback()
|
||||
raise
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(description='文章配图生成器')
|
||||
parser.add_argument('--topic-id', help='选题ID,指定则为选题生成配图')
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.topic_id:
|
||||
print(f"为选题 {args.topic_id} 生成配图...")
|
||||
results = generate_for_topic(args.topic_id)
|
||||
print(json.dumps({"topic_id": args.topic_id, "images": results}, ensure_ascii=False))
|
||||
sys.exit(0)
|
||||
|
||||
"""测试主函数"""
|
||||
generator = ImageGenerator()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user