import json import os from datetime import datetime from pathlib import Path from .database import SessionLocal, init_db from .models import ( Topic, TopicField, TopicConfigField, TopicStatusConfig, User, Case, LLMConfig, SystemConfig, PlatformConfig ) import bcrypt 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" CASES_FILE = PROJECT_ROOT / "automation" / "data" / "initial_cases.json" DEFAULT_ADMIN_USERNAME = os.getenv('DEFAULT_ADMIN_USERNAME', 'admin') DEFAULT_ADMIN_PASSWORD = os.getenv('DEFAULT_ADMIN_PASSWORD', 'admin123') def import_initial_data(): db = SessionLocal() try: if db.query(User).filter(User.username == DEFAULT_ADMIN_USERNAME).first() is None: hashed = bcrypt.hashpw(DEFAULT_ADMIN_PASSWORD.encode('utf-8'), bcrypt.gensalt()) admin = User( username=DEFAULT_ADMIN_USERNAME, password_hash=hashed.decode('utf-8'), role="admin" ) db.add(admin) db.commit() print(f"✅ 创建默认管理员: {DEFAULT_ADMIN_USERNAME}") if db.query(LLMConfig).count() == 0: default_llm = LLMConfig( name="default_expand", system_prompt="你是一个专业的内容创作者。", user_prompt_template="""你是一个专业的内容创作者,风格精炼、直接、切中要点。请将以下大纲扩展为完整的文章章节,要求如下: ### 选题信息 标题:{topic.get('title')} 领域:{topic.get('field_name')} 核心观点:{topic.get('core_concept', '')} 受众痛点:{topic.get('audience_pain', '')} 独特视角:{topic.get('unique_angle', '')} ### 当前章节 ## {section_title} {section_content} ### 输出要求 - 以 "## {section_title}" 开始 - 字数:200-300 字(精炼为主) - 语言:直白、有冲击力,避免空洞套话 - 使用 Markdown 格式 - 每个论点配具体案例或数据支撑 - 确保与整体文章调性一致 直接输出完整 Markdown 章节(包括标题和正文)。""", temperature=0.8, max_tokens=1000, model="stepfun-ai/step-3.5-flash", is_active=True ) db.add(default_llm) db.commit() print("✅ 插入默认 LLM 配置") default_system_configs = [ {"key": "collector_enabled", "value": "false", "description": "是否启用采集器"}, {"key": "scheduler_interval", "value": "daily", "description": "调度间隔:daily/hourly/weekly"}, ] for cfg in default_system_configs: if db.query(SystemConfig).filter(SystemConfig.key == cfg["key"]).first() is None: db.add(SystemConfig(**cfg)) if db.query(SystemConfig).filter(SystemConfig.key == "review_llm_id").first() is None: first_llm = db.query(LLMConfig).filter(LLMConfig.is_active == True).first() if first_llm: db.add(SystemConfig(key="review_llm_id", value=str(first_llm.id), description="审查使用的 LLM 配置 ID(留空则用环境变量默认值)")) db.commit() print("✅ 插入默认系统配置") if db.query(PlatformConfig).count() == 0: platforms = [ { "platform": "zhihu", "name": "知乎", "icon": "🔍", "default_format": "长文深度分析,1500-3000字,有数据支撑", "compliance_rules": { "max_length": 50000, "requires_authentication": False, "sensitive_words": ["敏感词示例1", "敏感词示例2"] }, "is_active": True }, { "platform": "wechat", "name": "微信公众号", "icon": "💚", "default_format": "公众号图文,800-1500字,亲切口语化", "compliance_rules": { "max_length": 20000, "requires_authentication": True }, "is_active": True }, { "platform": "xiaohongshu", "name": "小红书", "icon": "📕", "default_format": "图文笔记,300-800字,emoji+标签", "compliance_rules": { "max_length": 1000, "requires_tags": True, "max_tags": 10 }, "is_active": True } ] for p in platforms: db.add(PlatformConfig(**p)) db.commit() print("✅ 插入平台配置") if db.query(TopicField).count() == 0: fields = [ {"name": "未来工作方式", "icon": "💼", "color": "#667eea", "description": "远程工作、零工经济、职业转型", "sort_order": 1}, {"name": "AI与效率", "icon": "🤖", "color": "#764ba2", "description": "AI工具、数字助手、效率方法", "sort_order": 2}, {"name": "可持续生活", "icon": "🌿", "color": "#67c23a", "description": "环保、低碳、自然生活方式", "sort_order": 3}, {"name": "数字游民", "icon": "🌍", "color": "#409eff", "description": "旅行、地理自由、海外生活", "sort_order": 4}, {"name": "个人成长", "icon": "📚", "color": "#e6a23c", "description": "学习、技能、认知升级", "sort_order": 5}, {"name": "科技人文", "icon": "🔬", "color": "#f56c6c", "description": "科技伦理、数字生活反思", "sort_order": 6}, ] for f in fields: db.add(TopicField(**f)) db.commit() print("✅ 插入默认领域配置") if db.query(TopicStatusConfig).count() == 0: statuses = [ {"status": "pending", "label": "待处理", "color": "#E6A23C", "icon": "⏳", "sort_order": 1, "is_default": True}, {"status": "review", "label": "待审查", "color": "#F56C6C", "icon": "🔍", "sort_order": 2}, {"status": "draft", "label": "草稿", "color": "#909399", "icon": "📝", "sort_order": 3}, {"status": "ready", "label": "待发布", "color": "#67C23A", "icon": "✅", "sort_order": 4}, {"status": "published", "label": "已发布", "color": "#409EFF", "icon": "🚀", "sort_order": 5}, ] for s in statuses: db.add(TopicStatusConfig(**s)) db.commit() print("✅ 插入状态配置") field_map = {} for f in db.query(TopicField).all(): field_map[f.name] = f.id if db.query(Topic).count() == 0: if os.path.exists(TOPICS_FILE): topics = json.loads(open(TOPICS_FILE, encoding='utf-8').read()) seen = {} for t in topics: seen[t['id']] = t unique_topics = list(seen.values()) for t in unique_topics: field_id = field_map.get(t.get('field')) field_name = t.get('field') topic = Topic( id=t['id'], field_id=field_id, field_name=field_name, title=t['title'], format=t.get('format'), core_concept=t.get('core_concept'), audience_pain=t.get('audience_pain'), unique_angle=t.get('unique_angle'), priority=t.get('priority'), priority_score=t.get('priority_score', 0), total_score=t.get('total_score'), status=t.get('status', 'pending'), cases=t.get('cases', []), tags=t.get('tags', []), source_file=t.get('source_file'), ready_at=datetime.strptime(t['ready_at'], '%Y-%m-%d').date() if t.get('ready_at') else None, published_at=datetime.strptime(t['published_at'], '%Y-%m-%d').date() if t.get('published_at') else None, compliance_score=t.get('compliance_score'), platform_urls=t.get('platform_urls', {}) ) db.add(topic) db.commit() print(f"✅ 导入 {len(unique_topics)} 个选题") else: print(f"⚠️ 选题文件不存在: {TOPICS_FILE}") if db.query(Case).count() == 0: if os.path.exists(CASES_FILE): cases_data = json.loads(open(CASES_FILE, encoding='utf-8').read()) for c in cases_data: case = Case( id=c['id'], title=c['title'], field=c['field'], summary=c['summary'], key_metrics=c.get('key_metrics'), date=c.get('date'), source=c['source'], source_url=c.get('source_url'), credibility_rating=c.get('credibility_rating'), china_applicability=c.get('china_applicability') ) db.add(case) db.commit() print(f"✅ 导入 {len(cases_data)} 条案例") # 同步 PostgreSQL 自增序列 if os.getenv('USE_POSTGRES', 'true').lower() == 'true': try: from sqlalchemy import text tables = ["cases", "users", "content_calendar", "media_assets", "content_metrics", "content_tasks", "audit_logs", "task_logs", "topic_config_fields"] for table in tables: db.execute(text(f"SELECT setval(pg_get_serial_sequence('{table}', 'id'), COALESCE((SELECT MAX(id) FROM {table}), 0) + 1, false)")) db.commit() print("✅ PostgreSQL 自增序列已同步") except Exception as e: print(f"⚠️ 序列同步警告: {e}") print("✅ 初始化完成") except Exception as e: import traceback traceback.print_exc() print(f"初始化失败: {e}") db.rollback() finally: db.close() if __name__ == "__main__": init_db() import_initial_data()