feat: consolidate env config and add deployment files

- Add debug_font_path, demo_docs_dir, e2e_api_base_url to config.py
- Fix hardcoded paths in pp_structure_debug.py, create_demo_images.py
- Fix hardcoded paths in test files
- Update .env.example with new configuration options
- Update .gitignore to exclude AI development files (.claude/, openspec/, AGENTS.md, CLAUDE.md)
- Add production startup script (start-prod.sh)
- Add README.md with project documentation
- Add 1panel Docker deployment files (docker-compose.yml, Dockerfiles, nginx.conf)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
egg
2025-12-14 15:02:16 +08:00
parent 858d93155f
commit 86a6633000
31 changed files with 1177 additions and 252 deletions

View File

@@ -7,21 +7,43 @@ from typing import List, Optional
from pydantic_settings import BaseSettings
from pydantic import Field, model_validator
from pathlib import Path
import platform
from shutil import which
# Anchor all default paths to the backend directory to avoid scattering runtime folders
BACKEND_ROOT = Path(__file__).resolve().parent.parent.parent
PROJECT_ROOT = BACKEND_ROOT.parent
def _default_pandoc_path() -> str:
return which("pandoc") or "/usr/bin/pandoc"
def _default_font_dir() -> str:
candidates = []
system = platform.system()
if system == "Darwin":
candidates.extend(["/System/Library/Fonts", "/Library/Fonts"])
elif system == "Windows":
candidates.append(r"C:\Windows\Fonts")
else:
candidates.extend(["/usr/share/fonts", "/usr/local/share/fonts"])
for path in candidates:
if Path(path).exists():
return path
return candidates[0] if candidates else ""
class Settings(BaseSettings):
"""Application settings loaded from environment variables"""
# ===== Database Configuration =====
mysql_host: str = Field(default="mysql.theaken.com")
mysql_port: int = Field(default=33306)
mysql_user: str = Field(default="A060")
mysql_host: str = Field(default="localhost")
mysql_port: int = Field(default=3306)
mysql_user: str = Field(default="")
mysql_password: str = Field(default="")
mysql_database: str = Field(default="db_A060")
mysql_database: str = Field(default="")
@property
def database_url(self) -> str:
@@ -32,14 +54,16 @@ class Settings(BaseSettings):
)
# ===== Application Configuration =====
backend_host: str = Field(default="0.0.0.0")
backend_port: int = Field(default=8000)
frontend_host: str = Field(default="0.0.0.0")
frontend_port: int = Field(default=5173)
secret_key: str = Field(default="your-secret-key-change-this")
algorithm: str = Field(default="HS256")
access_token_expire_minutes: int = Field(default=1440) # 24 hours
# ===== External Authentication Configuration =====
external_auth_api_url: str = Field(default="https://pj-auth-api.vercel.app")
external_auth_api_url: str = Field(default="https://your-auth-api.example.com")
external_auth_endpoint: str = Field(default="/api/auth/login")
external_auth_timeout: int = Field(default=30)
token_refresh_buffer: int = Field(default=300) # Refresh tokens 5 minutes before expiry
@@ -441,8 +465,8 @@ class Settings(BaseSettings):
result_dir: str = Field(default=str(BACKEND_ROOT / "storage" / "results"))
# ===== PDF Generation Configuration =====
pandoc_path: str = Field(default="/opt/homebrew/bin/pandoc")
font_dir: str = Field(default="/System/Library/Fonts")
pandoc_path: str = Field(default_factory=_default_pandoc_path)
font_dir: str = Field(default_factory=_default_font_dir)
pdf_page_size: str = Field(default="A4")
pdf_margin_top: int = Field(default=20)
pdf_margin_bottom: int = Field(default=20)
@@ -456,7 +480,7 @@ class Settings(BaseSettings):
# ===== Translation Configuration (DIFY API) =====
enable_translation: bool = Field(default=True)
dify_base_url: str = Field(default="https://dify.theaken.com/v1")
dify_base_url: str = Field(default="https://your-dify-instance.example.com/v1")
dify_api_key: str = Field(default="") # Required: set in .env.local
dify_timeout: float = Field(default=120.0) # seconds
dify_max_retries: int = Field(default=3)
@@ -487,6 +511,23 @@ class Settings(BaseSettings):
log_level: str = Field(default="INFO")
log_file: str = Field(default=str(BACKEND_ROOT / "logs" / "app.log"))
# ===== Development & Testing Configuration =====
# Debug font path for visualization scripts (pp_structure_debug, create_demo_images)
debug_font_path: str = Field(
default="/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
description="Font path for debug visualization scripts"
)
# Demo documents directory for testing
demo_docs_dir: str = Field(
default=str(PROJECT_ROOT / "demo_docs"),
description="Directory containing demo documents for testing"
)
# E2E test API base URL
e2e_api_base_url: str = Field(
default="http://localhost:8000/api/v2",
description="Base URL for E2E tests"
)
@model_validator(mode="after")
def _normalize_paths(self):
"""Resolve all runtime paths to backend-rooted absolutes"""