Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.DS_Store
Thumbs.db

# 环境变量(保护敏感信息)
# Environment variables (protect sensitive info)
.env
.env.local
.env.*.local
Expand Down Expand Up @@ -36,7 +36,7 @@ yarn-error.log*
*.swp
*.swo

# 测试
# Testing
.pytest_cache/
.coverage
htmlcov/
Expand All @@ -45,17 +45,17 @@ htmlcov/
.cursor/
.claude/

# 文档与测试程序
# Docs and test programs
mydoc/
mytest/

# 日志文件
# Log files
backend/logs/
*.log

# 上传文件
# Uploaded files
backend/uploads/

# Docker 数据
# Docker data
data/backend/venv311/
backend/venv311/
14 changes: 7 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
FROM python:3.11

# 安装 Node.js (满足 >=18)及必要工具
# Install Node.js (>=18) and necessary tools
RUN apt-get update \
&& apt-get install -y --no-install-recommends nodejs npm \
&& rm -rf /var/lib/apt/lists/*

# uv 官方镜像复制 uv
# Copy uv from official image
COPY --from=ghcr.io/astral-sh/uv:0.9.26 /uv /uvx /bin/

WORKDIR /app

# 先复制依赖描述文件以利用缓存
# Copy dependency files first for caching
COPY package.json package-lock.json ./
COPY frontend/package.json frontend/package-lock.json ./frontend/
COPY backend/pyproject.toml backend/uv.lock ./backend/

# 安装依赖(Node + Python
# Install dependencies (Node + Python)
RUN npm ci \
&& npm ci --prefix frontend \
&& cd backend && uv sync --frozen
&& cd backend && uv lock && uv sync

# 复制项目源码
# Copy project source code
COPY . .

EXPOSE 3000 5001

# 同时启动前后端(开发模式)
# Start frontend and backend (dev mode)
CMD ["npm", "run", "dev"]
69 changes: 34 additions & 35 deletions backend/app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"""
MiroFish Backend - Flask应用工厂
MiroFish Backend - Flask application factory
"""

import os
import warnings

# 抑制 multiprocessing resource_tracker 的警告(来自第三方库如 transformers
# 需要在所有其他导入之前设置
# Suppress multiprocessing resource_tracker warnings (from third-party libraries like transformers)
# Must be set before all other imports
warnings.filterwarnings("ignore", message=".*resource_tracker.*")

from flask import Flask, request
Expand All @@ -17,76 +17,75 @@


def create_app(config_class=Config):
"""Flask应用工厂函数"""
"""Flask application factory function"""
app = Flask(__name__)
app.config.from_object(config_class)
# 设置JSON编码:确保中文直接显示(而不是 \uXXXX 格式)
# Flask >= 2.3 使用 app.json.ensure_ascii,旧版本使用 JSON_AS_ASCII 配置

# Set JSON encoding: ensure non-ASCII characters display directly (instead of \uXXXX format)
# Flask >= 2.3 uses app.json.ensure_ascii, older versions use JSON_AS_ASCII config
if hasattr(app, 'json') and hasattr(app.json, 'ensure_ascii'):
app.json.ensure_ascii = False
# 设置日志

# Set up logging
logger = setup_logger('mirofish')
# 只在 reloader 子进程中打印启动信息(避免 debug 模式下打印两次)

# Only print startup info in the reloader subprocess (avoid printing twice in debug mode)
is_reloader_process = os.environ.get('WERKZEUG_RUN_MAIN') == 'true'
debug_mode = app.config.get('DEBUG', False)
should_log_startup = not debug_mode or is_reloader_process

if should_log_startup:
logger.info("=" * 50)
logger.info("MiroFish-Offline Backend 启动中...")
logger.info("MiroFish-Offline Backend starting...")
logger.info("=" * 50)
# 启用CORS

# Enable CORS
CORS(app, resources={r"/api/*": {"origins": "*"}})

# --- 初始化 Neo4jStorage 单例(DI via app.extensions ---
# --- Initialize Neo4jStorage singleton (DI via app.extensions) ---
from .storage import Neo4jStorage
try:
neo4j_storage = Neo4jStorage()
app.extensions['neo4j_storage'] = neo4j_storage
if should_log_startup:
logger.info("Neo4jStorage 已初始化(连接 %s)", Config.NEO4J_URI)
logger.info("Neo4jStorage initialized (connected to %s)", Config.NEO4J_URI)
except Exception as e:
logger.error("Neo4jStorage 初始化失败: %s", e)
logger.error("Neo4jStorage initialization failed: %s", e)
# Store None so endpoints can return 503 gracefully
app.extensions['neo4j_storage'] = None
# 注册模拟进程清理函数(确保服务器关闭时终止所有模拟进程)

# Register simulation process cleanup function (ensure all simulation processes are terminated when the server shuts down)
from .services.simulation_runner import SimulationRunner
SimulationRunner.register_cleanup()
if should_log_startup:
logger.info("已注册模拟进程清理函数")
# 请求日志中间件
logger.info("Simulation process cleanup function registered")

# Request logging middleware
@app.before_request
def log_request():
logger = get_logger('mirofish.request')
logger.debug(f"请求: {request.method} {request.path}")
logger.debug(f"Request: {request.method} {request.path}")
if request.content_type and 'json' in request.content_type:
logger.debug(f"请求体: {request.get_json(silent=True)}")
logger.debug(f"Request body: {request.get_json(silent=True)}")

@app.after_request
def log_response(response):
logger = get_logger('mirofish.request')
logger.debug(f"响应: {response.status_code}")
logger.debug(f"Response: {response.status_code}")
return response
# 注册蓝图

# Register blueprints
from .api import graph_bp, simulation_bp, report_bp
app.register_blueprint(graph_bp, url_prefix='/api/graph')
app.register_blueprint(simulation_bp, url_prefix='/api/simulation')
app.register_blueprint(report_bp, url_prefix='/api/report')
# 健康检查

# Health check
@app.route('/health')
def health():
return {'status': 'ok', 'service': 'MiroFish-Offline Backend'}

if should_log_startup:
logger.info("MiroFish-Offline Backend 启动完成")

return app
logger.info("MiroFish-Offline Backend startup complete")

return app
2 changes: 1 addition & 1 deletion backend/app/api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
API路由模块
API routing module
"""

from flask import Blueprint
Expand Down
Loading