Files
bigscreen/init_database.py
brunoandClaude fe184bf8ba fix: 修复后端配置、API路由和数据库模型字段映射问题
主要修复内容:

## 后端配置修复
- 修复环境变量别名映射(POSTGRES_* → database_*, BACKEND_PORT → port)
- 添加数据库密码 URL 编码处理,支持特殊字符
- 添加 /health 健康检查端点用于启动脚本检测

## API 路由修复
- 移除 stats 和 tenant 路由的重复 /api/v1 前缀
- 修复路由挂载导致的 404 问题

## 数据库模型字段映射修复
- stats.py: 修正所有模型导入和字段名
  - UserHealthData.record_time → data_timestamp
  - UserAlert.severity → severity_level
  - UserAlert.created_at → timestamp
  - DeviceInfo.device_sn → serial_number
  - DeviceMessage.is_read → message_status 状态检查
- tenant.py: Organization → OrgInfo
- 添加 HealthAnomaly 模型用于异常数据统计

## 数据库初始化
- 新增 init_database.py 脚本,支持 FastAPI 异步架构
- 自动创建所有数据表并按类别分组显示

## 启动脚本增强
- 添加端口占用自动检测和释放功能
- 增强进度输出和错误日志显示
- 优化服务健康检查机制

测试状态:
- ✅ 后端服务正常启动(端口 8008)
- ✅ 前端服务正常启动(端口 8118)
- ✅ Stats API 接口测试通过
- ✅ Tenant API 接口测试通过
- ✅ 数据库成功初始化(ljwx_bigscreen)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
2025-12-03 23:03:02 +08:00

120 lines
4.4 KiB
Python
Executable File

#!/usr/bin/env python3
"""
PostgreSQL 数据库初始化脚本
为 FastAPI 应用创建所有表结构
"""
import asyncio
import sys
import os
from pathlib import Path
# 添加项目路径
sys.path.insert(0, str(Path(__file__).parent / "backend"))
# 设置环境变量(从 .env 读取)
from dotenv import load_dotenv
load_dotenv()
async def init_database():
"""初始化数据库"""
try:
from app.core.config import settings
from app.db.base import Base
from app.core.database import engine
# 导入所有模型以确保它们被注册
from app.models import (
health, alert, device, user, message,
org, config, audit, meeting
)
print("=" * 70)
print("PostgreSQL 数据库初始化开始")
print("=" * 70)
print(f"📦 应用: {settings.app_name} v{settings.app_version}")
print(f"🗄️ 数据库: {settings.database_name}")
print(f"🔗 主机: {settings.database_host}:{settings.database_port}")
print(f"👤 用户: {settings.database_user}")
print("=" * 70)
# 创建所有表
print("\n正在创建数据库表...")
async with engine.begin() as conn:
# 删除所有表(如果存在)
print(" ⚠️ 删除旧表(如果存在)...")
await conn.run_sync(Base.metadata.drop_all)
# 创建所有表
print(" ✨ 创建新表...")
await conn.run_sync(Base.metadata.create_all)
print("\n✅ 数据库表创建完成!\n")
# 验证表创建
from sqlalchemy import inspect, text
async with engine.connect() as conn:
# 获取所有表名
def get_tables(connection):
inspector = inspect(connection)
return inspector.get_table_names()
tables = await conn.run_sync(get_tables)
print(f"📊 共创建 {len(tables)} 个表:")
print("-" * 70)
# 按类别分组显示表
categories = {
"健康数据": ["t_user_health_data", "t_user_health_data_daily", "t_user_health_data_weekly", "t_health_summary_daily"],
"告警管理": ["t_alert_info", "t_alert_log", "t_alert_rules", "t_user_alerts", "t_health_anomaly", "t_event_alarm_queue"],
"设备管理": ["t_device_info", "t_device_user", "t_device_config", "t_device_status_log"],
"用户管理": ["t_user", "t_user_profile"],
"组织架构": ["t_org_info", "t_user_org", "t_position", "t_user_position", "t_org_closure", "t_org_manager_cache"],
"消息通知": ["t_device_message", "t_notification_config", "t_notification_log"],
"系统配置": ["t_customer", "t_customer_config", "t_system_config", "t_api_key"],
"审计日志": ["t_audit_log", "t_audit_operation_config"],
"会议室": ["t_meeting_room"]
}
categorized = set()
for category, table_list in categories.items():
found = [t for t in tables if t in table_list]
if found:
print(f"\n{category}:")
for table in sorted(found):
print(f" ✓ {table}")
categorized.add(table)
# 显示未分类的表
uncategorized = set(tables) - categorized
if uncategorized:
print(f"\n其他:")
for table in sorted(uncategorized):
print(f" ✓ {table}")
# 测试数据库连接
print("\n" + "-" * 70)
print("正在测试数据库连接...")
result = await conn.execute(text("SELECT version();"))
row = result.fetchone()
print(f" PostgreSQL 版本: {row[0][:60]}...")
print("\n" + "=" * 70)
print("✅ 数据库初始化成功完成!")
print("=" * 70)
print("\n💡 提示:")
print(" - 可以使用 start_app.sh 启动应用")
print(" - API 文档: http://localhost:8008/docs")
print(" - 大屏地址: http://localhost:8118/bigscreen")
print()
except Exception as e:
print(f"\n❌ 错误: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
asyncio.run(init_database())