This commit is contained in:
2026-04-24 16:02:16 +08:00
commit 1d6f0cc370
66 changed files with 9990 additions and 0 deletions

126
run.py Normal file
View File

@@ -0,0 +1,126 @@
"""
故事提取工具 - 入口脚本
支持开发模式和 PyInstaller 打包模式
"""
import os
import sys
import shutil
import socket
import webbrowser
import threading
import time
def get_base_dir() -> str:
"""获取基础目录"""
if getattr(sys, 'frozen', False):
return os.path.dirname(sys.executable)
else:
return os.path.dirname(os.path.abspath(__file__))
def cleanup_data(base_dir: str):
"""启动时清理数据库缓存和临时文件"""
print("正在清理上次运行的数据...")
# 实际数据目录(开发模式下在 backend/ 下,打包后在 exe 同级目录下)
if getattr(sys, 'frozen', False):
data_dir = base_dir
else:
data_dir = os.path.join(base_dir, "backend")
# 清理数据库
db_dir = os.path.join(data_dir, "data")
if os.path.exists(db_dir):
for f in os.listdir(db_dir):
if f.endswith((".db", ".db-wal", ".db-shm", ".db-journal")):
try:
os.remove(os.path.join(db_dir, f))
except Exception:
pass
# 清理上传的文件
uploads_dir = os.path.join(data_dir, "uploads")
if os.path.exists(uploads_dir):
for subdir in ["transcripts", "persons", "photos"]:
sub = os.path.join(uploads_dir, subdir)
if os.path.exists(sub):
shutil.rmtree(sub, ignore_errors=True)
# 清理导出文件
exports_dir = os.path.join(data_dir, "exports")
if os.path.exists(exports_dir):
shutil.rmtree(exports_dir, ignore_errors=True)
# 重新创建目录结构
for d in [db_dir, uploads_dir, exports_dir]:
os.makedirs(d, exist_ok=True)
for sub in ["transcripts", "persons", "photos"]:
os.makedirs(os.path.join(uploads_dir, sub), exist_ok=True)
print("清理完成!")
def find_free_port(start_port: int = 8000) -> int:
"""找到一个可用端口"""
for port in range(start_port, start_port + 100):
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(("127.0.0.1", port))
return port
except OSError:
continue
return start_port
def open_browser(port: int):
"""延迟打开浏览器"""
time.sleep(2)
url = f"http://localhost:{port}"
print(f"\n正在打开浏览器: {url}")
webbrowser.open(url)
def main():
base_dir = get_base_dir()
# 1. 清理数据
cleanup_data(base_dir)
# 2. 找可用端口
port = find_free_port(8000)
if port != 8000:
print(f"端口 8000 被占用,使用端口 {port}")
# 3. 启动服务
print(f"\n{'='*50}")
print(f" 故事提取工具")
print(f" 访问地址: http://localhost:{port}")
print(f" 按 Ctrl+C 停止服务")
print(f"{'='*50}\n")
# 延迟打开浏览器(不阻塞主线程)
threading.Thread(target=open_browser, args=(port,), daemon=True).start()
# 启动 uvicorn
os.environ["APP_PORT"] = str(port)
if getattr(sys, 'frozen', False):
# 打包模式:直接 import 并运行
import uvicorn
# 把 backend 目录加到 path让 app 包能被找到
backend_dir = os.path.join(base_dir, "backend")
if backend_dir not in sys.path:
sys.path.insert(0, backend_dir)
uvicorn.run("app.main:app", host="0.0.0.0", port=port, log_level="info")
else:
# 开发模式
import uvicorn
backend_dir = os.path.join(base_dir, "backend")
if backend_dir not in sys.path:
sys.path.insert(0, backend_dir)
uvicorn.run("app.main:app", host="0.0.0.0", port=port, log_level="info")
if __name__ == "__main__":
main()