diff --git a/platform/backend/app/api/system.py b/platform/backend/app/api/system.py
index d521390..607e010 100644
--- a/platform/backend/app/api/system.py
+++ b/platform/backend/app/api/system.py
@@ -22,89 +22,69 @@ DATA_DIR = PROJECT_ROOT / "automation" / "data"
router = APIRouter(prefix="/api/system", tags=["system"])
-@router.get("/status", response_model=SystemStatus)
+@router.get("/status")
def get_status(db: Session = Depends(get_db)):
- """系统状态概览"""
+ """系统状态概览 - 返回前端兼容格式"""
total = db.query(Topic).count()
by_status_result = db.query(Topic.status, func.count()).group_by(Topic.status).all()
by_status = {status: count for status, count in by_status_result}
- # 确保返回所有状态,避免前端 undefined
- for key in ('pending', 'ready', 'published'):
- by_status.setdefault(key, 0)
- ready = db.query(Topic).filter(Topic.status == "ready").all()
+ # 确保返回所有状态
+ status_map = {
+ '待处理': by_status.get('pending', 0),
+ '待审查': by_status.get('review', 0),
+ '待发布': by_status.get('ready', 0),
+ '已发布': by_status.get('published', 0)
+ }
- today_str = date.today().isoformat()
- # 计算今日文章数:查找 releases/2026-04-16 目录下的 html 文件
- # 这里简单统计数据库中 created_at 为今天的文章(不完全准确)
- today_articles = db.query(Article).filter(
- func.date(Article.created_at) == date.today()
+ # 计算今日新增
+ today = date.today()
+ today_count = db.query(Topic).filter(
+ func.date(Topic.created_at) == today
).count()
- # 合规率:假设所有 ready 的都是合规的(实际从report读取)
- # 可以后续优化
-
- # 获取最后一次优化时间
- last_opt = db.query(Article).filter(
- Article.status == "optimized"
- ).order_by(Article.created_at.desc()).first()
-
- return SystemStatus(
- total_topics=total,
- topics_by_status=by_status,
- ready_topics=ready,
- today_articles=today_articles,
- compliance_rate=100.0, # placeholder
- last_optimization=last_opt.created_at if last_opt else None
- )
+ return {
+ "stats": {
+ "total": total,
+ "pending": status_map['待处理'],
+ "review": status_map['待审查'],
+ "ready": status_map['待发布'],
+ "published": status_map['已发布'],
+ "today": today_count
+ }
+ }
@router.post("/generate/run", dependencies=[Depends(get_current_user)])
def trigger_generation(topic_id: str = None, db: Session = Depends(get_db)):
- """手动触发内容创作任务
-
- Args:
- topic_id: 可选,指定要创作的选题ID。不指定则创作优先级最高的待处理选题。
- """
+ """手动触发内容创作任务"""
try:
result = run_creator(topic_id)
if not result["ok"]:
raise HTTPException(status_code=500, detail=result["error"])
-
- from ..core.sync import sync_all_topics
sync_all_topics()
-
return {"message": "Generation triggered", "result": result}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/optimize/run", dependencies=[Depends(get_current_user)])
def trigger_optimization(topic_ids: List[str] = None, db: Session = Depends(get_db)):
- """手动触发合规优化任务
-
- Args:
- topic_ids: 可选,指定要优化的选题ID列表。不指定则优化所有 draft 状态文章。
- """
+ """手动触发合规优化任务"""
try:
result = run_optimizer(topic_ids)
if not result["ok"]:
raise HTTPException(status_code=500, detail=result["error"])
-
report = result.get("report")
if report:
- from ..core.sync import sync_all_topics
sync_all_topics()
- return {
- "message": "Optimization completed",
- "summary": report["summary"]
- }
+ return {"message": "Optimization completed", "summary": report["summary"]}
else:
- return {"message": "Optimization completed but no report found", "stdout": result.get("stdout", "")}
+ return {"message": "Optimization completed", "stdout": result.get("stdout", "")}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/logs/{log_date}", dependencies=[Depends(get_current_user)])
def get_logs(log_date: str, log_type: str = "creator"):
- """读取日志文件内容,log_type: creator, optimizer, collector"""
+ """读取日志文件内容"""
log_file = LOGS_DIR / f"{log_type}_{log_date}.log"
if not log_file.exists():
raise HTTPException(status_code=404, detail=f"Log file not found: {log_file}")
@@ -114,56 +94,35 @@ def get_logs(log_date: str, log_type: str = "creator"):
@router.get("/pipeline/status", dependencies=[Depends(get_current_user)])
def get_pipeline_status():
- """获取流水线各模块状态(最后运行时间和结果)"""
+ """获取流水线各模块状态"""
try:
- # 读取选题文件
topics_file = DATA_DIR / "sustainability_topics.json"
topics = []
if topics_file.exists():
topics = json.loads(topics_file.read_text(encoding='utf-8'))
-
- # 统计状态分布
status_counts = {}
for t in topics:
s = t.get('status', 'unknown')
status_counts[s] = status_counts.get(s, 0) + 1
-
- # 检查各日志文件的最新修改时间
log_files = {
"collector": LOGS_DIR / f"collector_{date.today().isoformat()}.log",
"creator": LOGS_DIR / f"creator_{date.today().isoformat()}.log",
"optimizer": LOGS_DIR / f"optimizer_{date.today().isoformat()}.log",
}
-
pipeline_status = {}
for name, log_file in log_files.items():
if log_file.exists():
mtime = datetime.fromtimestamp(log_file.stat().st_mtime)
- pipeline_status[name] = {
- "last_run": mtime.isoformat(),
- "exists": True,
- "size_bytes": log_file.stat().st_size
- }
- # 简单推断成功/失败(TODO: 解析日志加强)
- last_lines = log_file.read_text(encoding='utf-8').splitlines()[-10:]
- has_error = any("error" in line.lower() or "失败" in line or "failed" in line.lower() for line in last_lines)
- pipeline_status[name]["has_error"] = has_error
+ pipeline_status[name] = {"last_run": mtime.isoformat(), "exists": True}
else:
pipeline_status[name] = {"exists": False, "last_run": None}
-
- return {
- "topics_count": len(topics),
- "status_distribution": status_counts,
- "pipeline_modules": pipeline_status,
- "data_dir": str(DATA_DIR),
- "logs_dir": str(LOGS_DIR)
- }
+ return {"topics_count": len(topics), "status_distribution": status_counts, "pipeline_modules": pipeline_status}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/sync/run")
def run_sync():
- """手动触发数据同步(流水线JSON → 平台数据库)"""
+ """手动触发数据同步"""
try:
sync_all_topics()
return {"message": "Sync completed"}
@@ -172,16 +131,13 @@ def run_sync():
@router.get("/automation/topics")
def list_automation_topics():
- """直接读取自动化流水线的选题JSON(供调试)"""
+ """直接读取自动化流水线的选题 JSON"""
try:
topics_file = DATA_DIR / "sustainability_topics.json"
if not topics_file.exists():
raise HTTPException(status_code=404, detail="Topics JSON not found")
topics = json.loads(topics_file.read_text(encoding='utf-8'))
- return {
- "count": len(topics),
- "topics": topics[-50:] # 只返回最近50个,避免过大
- }
+ return {"count": len(topics), "topics": topics[-50:]}
except json.JSONDecodeError as e:
raise HTTPException(status_code=500, detail=f"JSON parse error: {e}")
except Exception as e:
@@ -189,9 +145,9 @@ def list_automation_topics():
@router.post("/refresh")
def refresh_all():
- """刷新所有数据:同步JSON + 更新状态"""
+ """刷新所有数据"""
try:
sync_all_topics()
return {"message": "Refresh completed"}
except Exception as e:
- raise HTTPException(status_code=500, detail=str(e))
\ No newline at end of file
+ raise HTTPException(status_code=500, detail=str(e))
diff --git a/platform/frontend/debug.html b/platform/frontend/debug.html
new file mode 100644
index 0000000..25f58a9
--- /dev/null
+++ b/platform/frontend/debug.html
@@ -0,0 +1,194 @@
+
+
+
+
+
+
+ 宇之然内容创作平台 - Vue调试
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
🔍 Vue调试控制台
+
+
+
+ 调试输出:
+ {{ log }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/platform/frontend/diagnostic.html b/platform/frontend/diagnostic.html
new file mode 100644
index 0000000..d976bf9
--- /dev/null
+++ b/platform/frontend/diagnostic.html
@@ -0,0 +1,269 @@
+
+
+
+
+
+
+ 宇之然内容创作平台 - 诊断测试
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
🔍 功能诊断测试
+
+
+
+
+
+
+
📋 选题管理功能测试
+
+
+
+
批量操作测试
+
+ ✅ 通过
+
+
+
+
数据加载测试
+
+ ✅ 通过
+
+
+
+
+
+
+
+
+
+
📄 系统日志功能测试
+
+
+
+
+
+
+
+
{{ logContent }}
+
+
+
+
+
👥 用户管理功能测试
+
+
+
用户列表
+
+
+
+
+
+
+ | ID |
+ 用户名 |
+ 角色 |
+ 操作 |
+
+
+
+
+ | {{ user.id }} |
+ {{ user.username }} |
+
+
+ {{ user.role === 'admin' ? '管理员' : '编辑' }}
+
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/platform/frontend/final-diagnostic.html b/platform/frontend/final-diagnostic.html
new file mode 100644
index 0000000..2ed0e08
--- /dev/null
+++ b/platform/frontend/final-diagnostic.html
@@ -0,0 +1,410 @@
+
+
+
+
+
+
+ 宇之然内容创作平台 - 综合诊断
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
🎯 Vue应用综合诊断与修复
+
+
+
+
+
+
+
+
+
+
+
+
+ 诊断日志:
+ {{ log }}
+
+
+
+
+
+
Vue状态
+
初始化: {{ vueInitialized ? '✅' : '❌' }}
+
数据绑定: {{ dataBindingWorking ? '✅' : '❌' }}
+
+
+
Element Plus
+
样式加载: {{ elementPlusStylesLoaded ? '✅' : '❌' }}
+
组件可用: {{ elementPlusComponentsAvailable ? '✅' : '❌' }}
+
+
+
功能状态
+
表格渲染: {{ tableRenderingWorking ? '✅' : '❌' }}
+
事件处理: {{ eventHandlingWorking ? '✅' : '❌' }}
+
+
+
+
+
+
+
📊 详细测试结果
+
+
+
+
+
{{ result.title }}
+
{{ result.description }}
+
+
+ {{ result.status === 'passed' ? '✅' : '❌' }}
+
+
+
+
+
+
还没有运行任何测试。请点击上方的"运行全面诊断"开始。
+
+
+
+
+
+
🔧 问题解决方案
+
+
+
方案1: 检查浏览器控制台错误
+
+ - 打开开发者工具(F12)
+ - 切换到Console选项卡
+ - 刷新页面并记录所有JavaScript错误
+ - 根据错误信息进行针对性修复
+
+
+
+
+
方案2: 简化Vue应用
+
+ - 移除所有Element Plus依赖
+ - 使用纯HTML/CSS/JS实现基本功能
+ - 确保Vue能正常工作
+ - 逐步添加复杂功能
+
+
+
+
+
方案3: 本地托管资源
+
+ - 下载Vue和Element Plus到本地
+ - 更新HTML中的CDN链接为本地路径
+ - 确保所有资源文件正确放置
+ - 重新测试页面功能
+
+
+
+
+
方案4: 重构页面结构
+
+ - 拆分复杂的Vue组件
+ - 简化数据结构和状态管理
+ - 确保每个功能模块独立工作
+ - 分阶段测试和验证
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/platform/frontend/final-solution.html b/platform/frontend/final-solution.html
new file mode 100644
index 0000000..7e9e50d
--- /dev/null
+++ b/platform/frontend/final-solution.html
@@ -0,0 +1,452 @@
+
+
+
+
+
+
+ 最终解决方案
+
+
+
+
+
+
+
+
宇之然内容创作平台 - Vue问题诊断
+
+
+
+
📋 问题描述
+
症状: 选题管理、系统日志、用户管理页面点击菜单后只显示标题,没有实际内容
+
可能原因: Vue应用初始化失败、Element Plus集成问题、CSS样式冲突等
+
+
+
+
+
🔍 快速诊断
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
📋 选题管理
+
+
+
+
+
+
+
+
+
+
+ 全部 (3)
+ 待处理 (1)
+ 待审查 (1)
+ 待发布 (1)
+
+
+
+
+
+
+
+
📄 系统日志
+
+
+
+
+
+
+
+
{{ logContent }}
+
+
+
+
+
👥 用户管理
+
+
+
用户列表
+
+
+
+
+
+
+ | ID |
+ 用户名 |
+ 角色 |
+ 创建时间 |
+ 操作 |
+
+
+
+
+ | {{ user.id }} |
+ {{ user.username }} |
+
+ 管理员
+ 编辑
+ |
+ {{ formatDate(user.created_at) }} |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+ `;
+
+ // 替换当前页面内容
+ document.documentElement.innerHTML = emergencyHTML;
+
+ document.getElementById('emergencyResult').innerHTML =
+ '✅ 紧急修复已应用!
' +
+ '页面已更新为简化版本,移除了复杂的依赖。
' +
+ '重新加载
';
+ }, 1000);
+ }
+
+ function addResult(message, type = 'info') {
+ const resultDiv = document.getElementById('testResults');
+ const colorClass = type === 'success' ? 'success' : type === 'error' ? 'error' : 'warning';
+ resultDiv.innerHTML +=
+ '' + message + '
';
+ }
+
+ function updateDetailedAnalysis() {
+ const analysisDiv = document.getElementById('detailedAnalysis');
+ let analysis = '';
+
+ analysis += '当前状态:
';
+ analysis += '';
+ analysis += '- Vue就绪: ' + (appData.vueReady ? '✅' : '❌') + '
';
+ analysis += '- DOM就绪: ' + (appData.domReady ? '✅' : '❌') + '
';
+ analysis += '- CSS就绪: ' + (appData.cssLoaded ? '✅' : '❌') + '
';
+ analysis += '
';
+
+ if (appData.errors.length > 0) {
+ analysis += '错误:
';
+ analysis += '';
+ appData.errors.forEach(error => {
+ analysis += '- ' + error + '
';
+ });
+ analysis += '
';
+ }
+
+ analysisDiv.innerHTML = analysis;
+ }
+
+ function generateSolutions() {
+ const solutionsDiv = document.getElementById('solutionsList');
+ let solutions = '';
+
+ solutions += '检查浏览器控制台: 按F12查看JavaScript错误';
+ solutions += '验证CDN资源: 确保Vue和Element Plus能正常下载';
+ solutions += '简化页面结构: 移除复杂依赖,使用纯HTML/CSS/JS';
+ solutions += '检查网络连接: 确认能访问外部资源';
+ solutions += '清除缓存: 尝试无痕模式或清除浏览器缓存';
+ solutions += '使用本地托管: 下载Vue和Element Plus到本地服务器';
+
+ solutionsDiv.innerHTML = solutions;
+ }
+
+ // 自动运行初始诊断
+ setTimeout(runQuickTest, 100);
+
+