import json import os from datetime import datetime from pathlib import Path from .database import SessionLocal, init_db from .models import Topic, User, Case, LLMConfig, SystemConfig import bcrypt # 计算项目根目录(backend/app/initial_data.py -> 上升3层到 yu-zhi-ran) 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: # 1. 导入选题数据 if db.query(Topic).count() == 0: if __import__('os').path.exists(TOPICS_FILE): topics = json.loads(open(TOPICS_FILE, encoding='utf-8').read()) # 去重:保留每个 ID 最后出现的记录 seen = {} for t in topics: seen[t['id']] = t unique_topics = list(seen.values()) for t in unique_topics: topic = Topic( id=t['id'], title=t['title'], field=t['field'], 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', []), 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}") else: print("数据库已有选题数据,跳过导入") # 3. 导入案例数据(如果为空) if db.query(Case).count() == 0: if __import__('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)} 条案例") else: print(f"⚠️ 案例文件不存在: {CASES_FILE}") # 4. 插入 LLM 默认配置 if db.query(LLMConfig).count() == 0: default_llm = LLMConfig( name="default_expand", system_prompt="你是一个专业的内容创作者。", user_prompt_template="""你是一个专业的内容创作者,风格精炼、直接、切中要点。请将以下大纲扩展为完整的文章章节,要求如下: ### 选题信息 标题:{topic.get('title')} 领域:{topic.get('field')} 核心观点:{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 配置") # 5. 插入系统配置默认值 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)) db.commit() print("✅ 插入默认系统配置") # 2. 创建默认管理员用户(bcrypt 哈希) admin_exists = db.query(User).filter(User.username == DEFAULT_ADMIN_USERNAME).first() if not admin_exists: 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}") else: # 如果管理员已存在但密码为空,更新为默认密码的哈希 if not admin_exists.password_hash: hashed = bcrypt.hashpw(DEFAULT_ADMIN_PASSWORD.encode('utf-8'), bcrypt.gensalt()) admin_exists.password_hash = hashed.decode('utf-8') db.commit() print(f"✅ 更新管理员密码") print(f"管理员已存在: {DEFAULT_ADMIN_USERNAME}") except Exception as e: print(f"初始化失败: {e}") db.rollback() finally: db.close() if __name__ == "__main__": init_db() import_initial_data()