# KSP Operation Hangar 交接文档 最后更新:2026-05-28 本文档介绍 KSP Operation Hangar 后台项目本身,不包含 Wiki.js 页面生产、图片资产上传、Wiki 发布脚本和 KSP_wiki 内容维护。Wiki 相关工作流见 `handover/ksp_wiki_handover.md`。 ## 1. 项目定位 KSP Operation Hangar 是一个 Flask + SQLAlchemy 的 KSP 数据整理与任务运营后台。项目最初用于把 Excel 工作簿中的发动机、通信部件、燃料箱和载具成本数据导入数据库,随后扩展出任务资产、资产日志、状态节点和 Mission Ops 预览页面。 项目的主要目标是: - 将分散的 KSP Excel 数据转为可查询、可编辑、可导入的数据库记录。 - 提供 Web 后台管理 Engine、Communication、Tank、Vehicle Cost 等资料。 - 提供 Fuel Converter 工具和 API,支持燃料体积与质量换算。 - 管理任务资产、任务日志和状态节点,用于构建任务运营视图。 - 通过 Mission Ops 页面按模拟时间查看任务状态、地点分布、未来事件和时间线。 当前项目更接近个人/小团队内部管理后台,不是面向公网的完整生产系统。鉴权、审计、自动化测试和正式权限隔离尚未完成。 ## 2. 代码结构总览 ```text KSP_Project/ ├── main.py ├── app/ │ ├── __init__.py │ ├── config.py │ ├── extensions.py │ ├── models.py │ ├── routes/ │ │ ├── api.py │ │ └── web.py │ ├── services/ │ │ ├── fuel_conversion.py │ │ ├── log_book_importer.py │ │ ├── workbook_importer.py │ │ └── workbook_inspector.py │ ├── static/ │ │ └── styles.css │ └── templates/ ├── migrations/ │ └── versions/ ├── scripts/ │ ├── import_log_book.py │ ├── import_workbook.py │ └── inspect_workbook.py ├── prototypes/ │ └── mission-ops/ ├── Dockerfile ├── docker-compose.yml ├── requirements.txt └── .env.example ``` 非后台范围说明: - `data/wiki/`、`data/KSP/wiki-*`、`scripts/wiki_*.py`、根目录 `vulture_shuttle*.html/md` 属于 Wiki 工作流,见另一份交接文档。 - `prototypes/mission-ops/` 是早期静态 Mission Ops 原型,虽然不是正式 Flask 页面,但可作为 UI 设计参考。 ## 3. 运行入口与应用初始化 ### 3.1 入口文件 入口是 `main.py`: - 调用 `app.create_app()` 创建 Flask app。 - 本地直接运行时监听 `0.0.0.0:APP_PORT`。 - 当 `APP_ENV=development` 时启用 Flask debug。 常用本地命令: ```powershell pip install -r requirements.txt python main.py ``` 默认访问地址: ```text http://127.0.0.1:8000/ ``` ### 3.2 Flask app factory `app/__init__.py` 中的 `create_app()` 负责: - 创建 Flask 应用。 - 加载 `app.config.Config`。 - 初始化 `db` 与 `migrate`。 - 注册 `web_bp` 和 `api_bp`。 - 注册 Jinja filter:`fmt_decimal`。 `fmt_decimal` 用于在模板中格式化 Decimal,默认保留 4 位并去掉尾随零。 ### 3.3 扩展对象 `app/extensions.py` 定义全局扩展对象: - `db = SQLAlchemy()` - `migrate = Migrate()` 不要在模型或路由中重新创建扩展实例,统一从 `app.extensions` 导入。 ## 4. 依赖 `requirements.txt` 当前依赖: ```text Flask>=3.1,<4.0 Flask-SQLAlchemy>=3.1,<4.0 Flask-Migrate>=4.0,<5.0 python-dotenv>=1.0,<2.0 psycopg[binary]>=3.2,<4.0 openpyxl>=3.1,<4.0 gunicorn>=23.0,<24.0 ``` 用途说明: - Flask:Web 框架。 - Flask-SQLAlchemy:ORM。 - Flask-Migrate:Alembic 迁移集成。 - python-dotenv:读取 `.env`。 - psycopg:PostgreSQL 驱动。 - openpyxl:读取 Excel 工作簿。 - gunicorn:容器/生产运行 WSGI server。 ## 5. 配置读取方式 ### 5.1 配置入口 配置逻辑在 `app/config.py`。 启动时会执行: ```python load_dotenv(BASE_DIR / ".env") ``` 也就是说,项目根目录的 `.env` 是运行时真实配置来源;`.env.example` 只提供安全示例,不包含真实凭据。 ### 5.2 数据库连接 `_build_database_uri()` 读取下列变量: ```text PGHOST PGPORT PGUSER PGPASSWORD PGDATABASE ``` 如果这些变量全部存在,则拼接 PostgreSQL URI: ```text postgresql+psycopg://:@:/ ``` 如果任一 PostgreSQL 配置缺失,则回退到本地 SQLite: ```text instance/ksp.sqlite3 ``` 注意:生产或 NAS 部署应使用 PostgreSQL。SQLite 主要用于临时本地开发。 ### 5.3 应用配置项 `Config` 支持的主要变量: | 变量 | 默认值 | 说明 | | --- | --- | --- | | `APP_ENV` | `development` | 控制 debug 等环境行为 | | `APP_PORT` | `8000` | 本地 Flask 启动端口,也被 docker-compose 用作宿主机端口 | | `APP_SECRET_KEY` | `development-only-secret-key` | Flask session secret | | `PROJECT_TITLE` | `KSP Data Hangar` | 页面标题/项目展示名 | | `WORKBOOK_PATH` | `KSP Engine Tweak Chart.xlsx` | 默认 KSP Excel 工作簿路径 | | `SQLALCHEMY_ECHO` | `false` | 是否输出 SQL 日志 | `.env.example` 还包含 Wiki.js 相关变量,但后台应用本身只依赖 `PGDATABASE`,不直接使用 `WIKIDATABASE` 或 Wiki 登录信息。 ## 6. 数据模型 模型位于 `app/models.py`。所有核心表使用 UUID 主键;多数模型继承 `TimestampMixin`,提供 `created_at` 和 `updated_at`。 ### 6.1 基础数据模型 | 模型 | 表 | 用途 | | --- | --- | --- | | `EngineFamily` | `engine_families` | 发动机家族/基础型号 | | `EngineVariant` | `engine_variants` | 发动机配置项,如燃料、环境、推力、比冲等 | | `CommunicationPart` | `communication_parts` | 通信部件、天线类型、范围、功耗等 | | `TankSpec` | `tank_specs` | 燃料箱质量、湿重、干重、体积与质量比 | | `VehicleCost` | `vehicle_costs` | 载具发射成本或价格数据 | 发动机数据注意事项: - 源 Excel 中 `Engine + Config Name` 不是可靠唯一键。 - 早期巡检发现 48 组 `Engine + Config Name` 冲突。 - 即使加入 Fuel Type,仍有 19 组冲突。 - 因此数据库采用 UUID 主键,自然键只用于展示、筛选和告警。 ### 6.2 任务资产模型 | 模型 | 表 | 用途 | | --- | --- | --- | | `Asset` | `assets` | 任务资产,例如母舰、航天飞机、站点、基地 | | `AssetLogEntry` | `asset_log_entries` | 资产日志,支持事件点与状态区间 | | `AssetStateNode` | `asset_state_nodes` | 状态区间内的时间节点和细节说明 | 任务运营页面主要基于这三张表构建: - 当前状态。 - 未来事件。 - 任务标签和地点分组。 - 状态板、地点板和时间线。 `Asset.is_retired` 用于排除退役资产。 ## 7. 数据迁移 迁移目录:`migrations/versions/` 当前有 6 个迁移: | 文件 | 作用 | | --- | --- | | `f1fa035d3afe_initial_schema.py` | 初始 schema | | `6c2a57f2b1e9_add_asset_log_tables.py` | 增加资产日志表 | | `f4f0c9c9426e_add_asset_state_nodes.py` | 增加状态节点表 | | `8bbf69ea2013_add_retired_flag_to_assets.py` | 增加资产退役标记 | | `0f1b9bb2156c_add_detail_to_asset_state_nodes.py` | 状态节点增加 detail 字段 | | `83be4d38636d_expand_communication_range_precision.py` | 扩展通信距离精度 | 常用命令: ```powershell python -m flask --app main:app db upgrade ``` 创建新迁移: ```powershell python -m flask --app main:app db migrate -m "message" python -m flask --app main:app db upgrade ``` 如果是首次初始化且没有 `migrations/`,才需要: ```powershell python -m flask --app main:app db init ``` ## 8. Web 后台功能 Web 路由在 `app/routes/web.py`,蓝图名称为 `web_bp`。 ### 8.1 Dashboard 与工具 | 路径 | 用途 | | --- | --- | | `/` | Dashboard,展示项目模块与数据冲突统计 | | `/fuel-converter` | 燃料体积/质量换算页面 | Dashboard 当前展示的冲突数固定为: - `duplicate_conflicts=48` - `duplicate_conflicts_with_fuel=19` ### 8.2 Engine Catalog | 路径 | 用途 | | --- | --- | | `/engines` | 发动机列表、搜索、筛选、排序、分页 | | `/engines/new` | 新建发动机及初始配置 | | `/engines/` | 发动机详情 | | `/engines//edit` | 编辑发动机家族和配置项 | | `/engines//variants/add` | 添加配置项 | | `/engines//variants//delete` | 删除配置项 | | `/engines//delete` | 删除发动机家族 | 相关模板: - `engine_list.html` - `engine_create.html` - `engine_detail.html` - `engine_edit.html` ### 8.3 Communication / Tank / Vehicle 这三类资源使用类似 CRUD 模式: | 资源 | 列表 | 新建 | 编辑 | 删除 | | --- | --- | --- | --- | --- | | Communication | `/communications` | `/communications/new` | `/communications//edit` | `/communications//delete` | | Tank | `/tanks` | `/tanks/new` | `/tanks//edit` | `/tanks//delete` | | Vehicle | `/vehicles` | `/vehicles/new` | `/vehicles//edit` | `/vehicles//delete` | 这些页面共用 `resource_edit.html` 做新增/编辑表单。 ### 8.4 Mission Assets | 路径 | 用途 | | --- | --- | | `/assets` | 任务资产目录,支持模拟时间、搜索、筛选、排序、分页 | | `/assets/new` | 新建任务资产 | | `/assets/` | 资产详情、日志列表、未来事件 | | `/assets//edit` | 编辑资产 | | `/assets//delete` | 删除资产及日志 | | `/assets/import-log-book` | 从 `log_book.xlsx` 导入资产日志 | | `/assets//entries/new` | 新增资产日志条目 | | `/assets//entries//edit` | 编辑资产日志条目与 State Nodes | | `/assets//entries//delete` | 删除资产日志条目 | 任务日志支持两类记录: - `event`:单点事件。 - `state`:状态区间,可带多个 `AssetStateNode`。 资产详情页会根据模拟时间计算: - 当前状态。 - 当前地点。 - 活跃/计划/历史状态。 - 未来事件,包括未来日志事件和未来 State Nodes。 ### 8.5 Mission Ops 页面 Mission Ops 页面基于数据库中的 Asset/AssetLogEntry/AssetStateNode 实时构建,而不是静态原型。 | 路径 | 用途 | | --- | --- | | `/missions` | 按 mission label 分组的任务列表 | | `/mission-preview` | 重定向到状态板 | | `/mission-preview/status-board` | 状态板,按运行状态分组 | | `/mission-preview/location-board` | 地点板,按地区/地点分组 | | `/mission-preview/asset-log` | 重定向到资产列表 | | `/mission-preview/timeline` | 时间线视图,支持 scale、范围、资产筛选 | 核心构建函数包括: - `_load_assets_with_logs()` - `_build_asset_snapshot()` - `_build_mission_board_rows()` - `_build_status_board_groups()` - `_build_location_board_groups()` - `_build_timeline_rows()` 时间线支持自动或手动范围、按 day/month/year 等 scale 展示,并计算 state segments 与 event nodes。 ## 9. API API 路由在 `app/routes/api.py`,蓝图路径前缀为 `/api/v1`。 | 路径 | 方法 | 用途 | | --- | --- | --- | | `/api/v1/health` | GET | 健康检查,返回 `status=ok` | | `/api/v1/fuel-converter/fuels` | GET | 返回燃料密度因子 | | `/api/v1/fuel-converter/convert` | GET/POST | 燃料体积/质量换算 | Fuel Converter 的业务逻辑在 `app/services/fuel_conversion.py`。 ## 10. 服务层与导入脚本 ### 10.1 Fuel conversion 文件:`app/services/fuel_conversion.py` 主要能力: - `list_fuel_factors()`:列出燃料密度因子。 - `convert_value(mode, raw_value)`:在体积与质量之间换算。 实现使用 `Decimal`,避免浮点误差。 ### 10.2 Workbook importer 文件:`app/services/workbook_importer.py` 导入对象: - Engine Database。 - Communication。 - Tank Chart。 - KSP Vehicle Cost。 入口脚本: ```powershell python scripts/import_workbook.py python scripts/import_workbook.py --replace python scripts/import_workbook.py --path "path/to/workbook.xlsx" ``` `--replace` 会清空导入相关表并重新导入。对真实数据库执行前应确认备份。 ### 10.3 Workbook inspector 文件:`app/services/workbook_inspector.py` 入口脚本: ```powershell python scripts/inspect_workbook.py python scripts/inspect_workbook.py --path "path/to/workbook.xlsx" ``` 用途: - 列出工作表和行数。 - 检查 Engine Database 表头。 - 汇总 Work Env 枚举。 - 统计自然键冲突。 - 分析字段稳定性。 ### 10.4 Log book importer 文件:`app/services/log_book_importer.py` 入口脚本: ```powershell python scripts/import_log_book.py python scripts/import_log_book.py --path "path/to/log_book.xlsx" ``` 导入逻辑: - 默认读取 `log_book.xlsx`。 - 忽略 `Overview` 和 `Model` sheet。 - 每个 sheet 对应一个 Asset。 - 按日期行解析事件与状态。 - 创建或更新 `Asset`、`AssetLogEntry`。 - 通过 `LOG_BOOK_ASSET_SPECS` 补充已知资产类型和初始信息。 当前 `LOG_BOOK_ASSET_SPECS` 仍有硬编码,需要随新资产扩展。 ## 11. 模板与前端 模板目录:`app/templates/` 主要模板: - `base.html`:页面外壳。 - `dashboard.html`:首页。 - `fuel_converter.html`:燃料换算工具。 - `engine_*.html`:发动机 CRUD。 - `communication_list.html`、`tank_list.html`、`vehicle_list.html`:基础资源列表。 - `asset_list.html`、`asset_detail.html`、`asset_entry_form.html`:任务资产与日志。 - `mission_list.html`:任务标签列表。 - `mission_status_board_preview.html`:状态板。 - `mission_location_board_preview.html`:地点板。 - `mission_timeline_preview.html`:时间线。 常用 partial: - `_datetime_picker_field.html` - `_mission_ops_tabs.html` - `_mission_preview_controls.html` - `_mission_preview_header.html` - `_mission_upcoming_events.html` 静态样式:`app/static/styles.css`。 当前前端为后台工具风格,未引入大型前端框架。 ## 12. Docker 与部署 ### 12.1 Dockerfile `Dockerfile` 使用 `python:3.12-slim`,安装 `requirements.txt`,复制项目文件,默认运行: ```text gunicorn --bind 0.0.0.0:8000 main:app ``` ### 12.2 docker-compose `docker-compose.yml` 定义 `web` 服务: - `env_file: .env` - 宿主机端口:`${APP_PORT:-8000}` - 容器端口:`8000` - restart policy:`unless-stopped` 启动: ```powershell docker compose up --build ``` ## 13. 当前已完成内容 - Flask app factory 与配置系统。 - PostgreSQL/SQLite 数据库连接。 - Alembic/Flask-Migrate 迁移体系。 - Engine/Communication/Tank/Vehicle 基础数据模型与 CRUD。 - Workbook 巡检和导入。 - Fuel Converter 页面与 API。 - Asset/AssetLogEntry/AssetStateNode 任务资产模型。 - Log Book 导入。 - Asset 详情页、日志编辑、State Nodes 编辑。 - Mission list、状态板、地点板、时间线页面。 - 未来事件展示与可跳转编辑。 - 表单验证错误弹窗和提交值保留。 - Dockerfile 与 docker-compose。 ## 14. 已知问题与后续 TODO ### 14.1 数据和导入 - Engine 自然键冲突仍需人工理解和治理。 - `LOG_BOOK_ASSET_SPECS` 是硬编码,新增资产时需要扩展或改为配置化。 - Workbook 导入缺少自动化测试和导入报告导出。 - 大规模重导入前需要备份,尤其是 `--replace`。 ### 14.2 后台功能 - 缺少用户登录、权限控制和审计日志。 - CRUD 操作没有软删除和恢复机制。 - Mission Ops 当前以读取资产日志为主,缺少更完整的任务计划/排程实体。 - Mission labels、state labels 等多值字段仍是文本拆分,未来可规范化成表。 - 资产关系、母舰/随舰载具关系仍未建成结构化模型。 ### 14.3 前端体验 - 样式仍集中在单一 CSS 文件。 - 前端表单校验较少,主要依赖后端验证。 - Mission Ops 时间线在数据量很大时可能需要性能优化。 - 原型目录中的静态页面应定期与正式 Flask 页面同步或归档。 ### 14.4 工程质量 - 缺少 pytest 或其他自动化测试。 - 缺少 CI。 - 缺少 lint/format 固定流程。 - 缺少导入脚本的 dry-run 模式。 - 缺少数据库备份/恢复文档。 ## 15. 新人接手建议 1. 先阅读 `app/config.py`、`app/__init__.py`、`app/models.py`,理解配置、初始化和数据模型。 2. 本地创建 `.env`,只使用示例键名,不提交真实凭据。 3. 执行 `python -m flask --app main:app db upgrade`,确认 schema 到最新。 4. 用 `python scripts/inspect_workbook.py` 了解 Excel 源数据质量。 5. 用 `python scripts/import_workbook.py` 导入基础数据。 6. 用 `python scripts/import_log_book.py` 导入任务资产日志。 7. 打开 `/assets`、`/missions`、`/mission-preview/timeline`,确认任务运营页面能从数据库生成内容。 8. 开发新功能时优先复用 `web.py` 里的表单解析、分页、时间处理和 Mission Ops 构建函数。 ## 16. 安全注意事项 - 不要提交 `.env`。 - 不要在日志或终端输出真实数据库密码。 - 写路径验证前优先使用临时记录,避免污染真实任务数据。 - 使用 `--replace` 导入前先确认数据库备份。 - Docker 生产部署前应更换 `APP_SECRET_KEY`,并补齐鉴权机制。