Files
KSP_project/handover/operation_hangar_handover.md

559 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
```
用途说明:
- FlaskWeb 框架。
- Flask-SQLAlchemyORM。
- Flask-MigrateAlembic 迁移集成。
- python-dotenv:读取 `.env`
- psycopgPostgreSQL 驱动。
- 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://<user>:<password>@<host>:<port>/<database>
```
如果任一 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/<uuid>` | 发动机详情 |
| `/engines/<uuid>/edit` | 编辑发动机家族和配置项 |
| `/engines/<uuid>/variants/add` | 添加配置项 |
| `/engines/<uuid>/variants/<uuid>/delete` | 删除配置项 |
| `/engines/<uuid>/delete` | 删除发动机家族 |
相关模板:
- `engine_list.html`
- `engine_create.html`
- `engine_detail.html`
- `engine_edit.html`
### 8.3 Communication / Tank / Vehicle
这三类资源使用类似 CRUD 模式:
| 资源 | 列表 | 新建 | 编辑 | 删除 |
| --- | --- | --- | --- | --- |
| Communication | `/communications` | `/communications/new` | `/communications/<uuid>/edit` | `/communications/<uuid>/delete` |
| Tank | `/tanks` | `/tanks/new` | `/tanks/<uuid>/edit` | `/tanks/<uuid>/delete` |
| Vehicle | `/vehicles` | `/vehicles/new` | `/vehicles/<uuid>/edit` | `/vehicles/<uuid>/delete` |
这些页面共用 `resource_edit.html` 做新增/编辑表单。
### 8.4 Mission Assets
| 路径 | 用途 |
| --- | --- |
| `/assets` | 任务资产目录,支持模拟时间、搜索、筛选、排序、分页 |
| `/assets/new` | 新建任务资产 |
| `/assets/<uuid>` | 资产详情、日志列表、未来事件 |
| `/assets/<uuid>/edit` | 编辑资产 |
| `/assets/<uuid>/delete` | 删除资产及日志 |
| `/assets/import-log-book` | 从 `log_book.xlsx` 导入资产日志 |
| `/assets/<uuid>/entries/new` | 新增资产日志条目 |
| `/assets/<uuid>/entries/<uuid>/edit` | 编辑资产日志条目与 State Nodes |
| `/assets/<uuid>/entries/<uuid>/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`,并补齐鉴权机制。