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:
@@ -5,7 +5,8 @@ from pathlib import Path
|
||||
from .database import SessionLocal, init_db
|
||||
from .models import (
|
||||
Topic, TopicField, TopicConfigField, TopicStatusConfig,
|
||||
User, Case, LLMConfig, SystemConfig, PlatformConfig
|
||||
User, Case, LLMConfig, SystemConfig, PlatformConfig,
|
||||
CollectorCategory, CollectorSource
|
||||
)
|
||||
import bcrypt
|
||||
|
||||
@@ -27,56 +28,36 @@ def import_initial_data():
|
||||
admin = User(
|
||||
username=DEFAULT_ADMIN_USERNAME,
|
||||
password_hash=hashed.decode('utf-8'),
|
||||
role="admin"
|
||||
role="admin",
|
||||
org_id="default"
|
||||
)
|
||||
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字,精炼有力
|
||||
- 每个论点配具体案例或数据支撑
|
||||
- 回答读者「所以呢」——为什么对他有用
|
||||
|
||||
#### 语言风格
|
||||
- 直白有冲击力,避免空洞套话
|
||||
- 用「你」或「我们」视角
|
||||
- 避免「首先其次最后」「综上所述」
|
||||
- 段落短,2-3句一段
|
||||
|
||||
#### SEO优化
|
||||
- 自然融入1-2个目标关键词
|
||||
- 开头句包含核心关键词
|
||||
- H3子标题有信息量
|
||||
|
||||
直接输出完整 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 配置")
|
||||
# 补充或更新 LLM 供应商配置(opencode-go 为主,nvidia 为备)
|
||||
expected = {
|
||||
"opencode-go": dict(provider="opencode-go", model="deepseek-v4-flash",
|
||||
base_url="https://opencode.ai/zen/go/v1", temperature=0.7, max_tokens=2000, is_active=True,
|
||||
user_prompt_template="将以下内容扩展为完整文章:\n{topic_title}\n{core_concept}"),
|
||||
"nvidia": dict(provider="nvidia", model="stepfun-ai/step-3.5-flash",
|
||||
base_url="https://integrate.api.nvidia.com/v1", temperature=0.5, max_tokens=2000, is_active=False,
|
||||
user_prompt_template="将以下内容扩展为完整章节:\n{section_content}"),
|
||||
}
|
||||
existing = {c.name: c for c in db.query(LLMConfig).all()}
|
||||
# 删除完全无意义的旧残留
|
||||
for name in list(existing.keys()):
|
||||
if name not in expected:
|
||||
db.delete(existing[name]); existing.pop(name)
|
||||
for name, cfg in expected.items():
|
||||
if name in existing:
|
||||
c = existing[name]
|
||||
for k, v in cfg.items():
|
||||
setattr(c, k, v)
|
||||
else:
|
||||
db.add(LLMConfig(name=name, **cfg))
|
||||
db.commit()
|
||||
print(f"✅ LLM 配置已同步: {', '.join(expected.keys())}")
|
||||
|
||||
default_system_configs = [
|
||||
{"key": "collector_enabled", "value": "false", "description": "是否启用采集器"},
|
||||
@@ -149,6 +130,34 @@ def import_initial_data():
|
||||
db.commit()
|
||||
print("✅ 插入默认领域配置")
|
||||
|
||||
if db.query(CollectorCategory).count() == 0:
|
||||
default_cats = [
|
||||
{"name": "循环消费", "search_query": "以旧换新 二手交易 闲置 循环 2026", "description": "以旧换新/二手交易/租赁经济 | 2025年二手交易额1.69万亿", "sort_order": 1, "is_active": True},
|
||||
{"name": "低碳出行", "search_query": "新能源车 骑行 绿色通勤 低碳出行 2026", "description": "新能源车/骑行/绿色出行 | 年产销破1000万辆", "sort_order": 2, "is_active": True},
|
||||
{"name": "干净饮食", "search_query": "干净饮食 有机食品 植物基 本地食材 2026", "description": "有机食品/植物基/本地食材 | 有机食品1247亿", "sort_order": 3, "is_active": True},
|
||||
{"name": "零浪费生活", "search_query": "零浪费 自带杯 极简生活 可持续时尚 2026", "description": "自带杯/极简/可持续时尚 | 自带杯笔记277万篇", "sort_order": 4, "is_active": True},
|
||||
{"name": "绿色家电与节能", "search_query": "绿色家电 一级能效 以旧换新 节能 2026", "description": "一级能效/国补政策 | 一级能效占比90%+", "sort_order": 5, "is_active": True},
|
||||
{"name": "碳普惠", "search_query": "碳账户 碳普惠 个人碳减排 蚂蚁森林 2026", "description": "碳账户/碳普惠/个人减排 | 武汉200万碳账户", "sort_order": 6, "is_active": True},
|
||||
{"name": "环保科技产品", "search_query": "环保科技 绿色产品 可持续材料 2026", "description": "可持续材料/绿色产品 | 购买占比超32%", "sort_order": 7, "is_active": True},
|
||||
{"name": "AI与效率", "search_query": "AI工具 人工智能 效率提升 2026", "description": "AI工具/效率方法/数字助手 | 2026年AI深度融入消费与生活", "sort_order": 8, "is_active": True},
|
||||
]
|
||||
for cd in default_cats:
|
||||
existing = db.query(CollectorCategory).filter(CollectorCategory.name == cd["name"]).first()
|
||||
if not existing:
|
||||
db.add(CollectorCategory(**cd))
|
||||
db.commit()
|
||||
print("✅ 插入默认采集类别和信息源")
|
||||
|
||||
db.commit()
|
||||
|
||||
# 补充缺失的类别和信息源(对已有数据库的迁移)
|
||||
for sd in [
|
||||
{"name": "AI工具搜索", "source_type": "web_search", "query": "AI工具 人工智能 效率提升 2026", "credibility": "medium", "focus": "AI与效率", "sort_order": 99, "is_active": True},
|
||||
]:
|
||||
if not db.query(CollectorSource).filter(CollectorSource.name == sd["name"]).first():
|
||||
db.add(CollectorSource(**sd))
|
||||
db.commit()
|
||||
|
||||
if db.query(TopicStatusConfig).count() == 0:
|
||||
statuses = [
|
||||
{"status": "pending", "label": "待处理", "color": "#E6A23C", "icon": "⏳", "sort_order": 1, "is_default": True},
|
||||
|
||||
Reference in New Issue
Block a user