chore: add project scripts, handover docs, and format guide
- guanghan_windows.py: Windows launcher script - inject_lightbox: lightbox injection utilities - handover docs: future missions proposal, vehicle creation guide, format guide Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
name: guanghan-launch-windows
|
||||||
|
description: Calculate upcoming Earth departure launch windows and lunar landing windows for the Guanghan Program. Use when given a date and asked to find launch windows, landing windows, or mission planning dates for Guanghan missions.
|
||||||
|
---
|
||||||
|
|
||||||
|
# 广寒计划发射窗口计算
|
||||||
|
|
||||||
|
广寒基地往返标准 LLO,每月有 2 个标准窗口。给定任意时间,计算最近的地球出发发射窗口及对应的月球着陆窗口。
|
||||||
|
|
||||||
|
## 核心参数
|
||||||
|
|
||||||
|
- 月球自转周期:27.32166 天
|
||||||
|
- 每月标准窗口数:2 个
|
||||||
|
- 地月转移耗时:5 天
|
||||||
|
- 参考窗 A:2024-09-23 12:13 UTC
|
||||||
|
- 参考窗 B:2024-10-01 14:34 UTC
|
||||||
|
|
||||||
|
## 使用方法
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python scripts/guanghan_windows.py "<日期时间>"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python scripts/guanghan_windows.py "2024-07-20"
|
||||||
|
python scripts/guanghan_windows.py "2024-12-15 08:00"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 输出
|
||||||
|
|
||||||
|
输出表格包含:
|
||||||
|
- 最近 4 个发射窗口(地球出发,UTC)
|
||||||
|
- 对应的着陆窗口(发射 + 5 天,UTC)
|
||||||
|
- 距查询时间的偏移量
|
||||||
@@ -0,0 +1,288 @@
|
|||||||
|
# 广寒计划后续任务提案(修订版 v3 — 按时间顺序排列)
|
||||||
|
|
||||||
|
> **状态:提案(Proposal)** — 待 Doctor Armor 审核批准
|
||||||
|
> **约束**:CZ-16 和 CZ-16A 共享发射基础设施,合计每 30 天最多发射 1 次。CZ-10E 独立,不受此限。
|
||||||
|
> **发射窗口**:由 `scripts/guanghan_windows.py` 计算,参考窗 A(2024-10-21 04:55)、窗 B(2024-10-29 03:15)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CZ-16/16A 发射排期总表
|
||||||
|
|
||||||
|
最近一次 CZ-16:2024-12-16(GHC-05 货运)。最近一次 CZ-16A:2024-12-08(GHC-05 载人)。
|
||||||
|
|
||||||
|
| # | ≥ 日期 | 发射 (UTC) | 着陆 (UTC) | 火箭 | 任务 | 载荷 |
|
||||||
|
|---|--------|-----------|-----------|------|------|------|
|
||||||
|
| 1 | 01-15 | **02-02 11:47** | 02-07 11:47 | CZ-16A | GHC-06 载人 | 嫦娥 + 吴刚#3(Block 2 新建) |
|
||||||
|
| 2 | 03-04 | **03-09 17:50** | 03-14 17:50 | CZ-16 | GHC-06 货运 | 广寒04 模块 → LEO |
|
||||||
|
| 3 | 04-08 | **04-25 10:57** | 04-30 10:57 | CZ-16 | GHC-07 货运 | 广寒05 模块 → LEO |
|
||||||
|
| 4 | 05-25 | **05-30 17:00** | 06-04 17:00 | CZ-16 | BL-04 | 冰轮#4(Block 2)→ 直接 TLI |
|
||||||
|
| 5 | 06-29 | **07-16 10:06** | 07-21 10:06 | CZ-16 | GHC-08 货运 | 广寒06 模块 → LEO |
|
||||||
|
| 6 | 08-15 | **08-20 16:10** | 08-25 16:10 | CZ-16 | GHC-09 货运 | 十字模块#2 + 2 走道 → LEO |
|
||||||
|
| 7 | 09-19 | **10-06 09:16** | 10-11 09:16 | CZ-16 | GHC-10 货运 | 加压月球车 + 2 走道 → LEO |
|
||||||
|
|
||||||
|
**CZ-10E 发射**(独立排期):
|
||||||
|
|
||||||
|
| 日期 | 任务 | 载荷 |
|
||||||
|
|------|------|------|
|
||||||
|
| 2025-04-06 01:34 | GHC-07 载人 | 嫦娥 → LLO,对接吴刚#2 |
|
||||||
|
| 2025-06-22 | JC-03 | 金蟾#3 → LEO 400×400 km |
|
||||||
|
| 2025-07-16 10:06 | GHC-08 载人 | 嫦娥 → LLO,对接吴刚#3 |
|
||||||
|
| 2025-11-10 15:19 | GHC-09 载人 | 嫦娥 → LLO,对接吴刚#2(首次半年轮换) |
|
||||||
|
| 2026-06-09 06:45 | GHC-10 载人 | 嫦娥 → LLO,对接吴刚#3(第二次半年轮换) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2025-02-02 GHC-06 载人发射(CZ-16A):吴刚#3 首航 + 乘组轮换
|
||||||
|
|
||||||
|
```
|
||||||
|
2025-02-02 11:47 CZ-16A 发射嫦娥-吴刚#3 组合体
|
||||||
|
2025-02-02 13:25 TLI 注入完成,嫦娥调头对接吴刚#3
|
||||||
|
2025-02-07 06:30 嫦娥近月制动,100×100 km LLO
|
||||||
|
2025-02-07 07:45 吴刚#3 分离
|
||||||
|
2025-02-07 11:47 吴刚#3 着陆东方海广寒基地
|
||||||
|
```
|
||||||
|
|
||||||
|
### 前期 EVA(2 月,等待广寒04 货运)
|
||||||
|
|
||||||
|
**EVA-1**(02-08,小组1,~8h):冰轮#1 ISRU 系统关闭——采矿车停机、SOE 电解模块降温、管路排空。
|
||||||
|
|
||||||
|
**EVA-2**(02-10,小组2,~8h):冰轮#1 ISRU 模块拆卸(12 吨)——拆除采矿车×2、电解模块、散热器阵列。组件暂存月面。冰轮#1 恢复为标准货运构型。
|
||||||
|
|
||||||
|
**EVA-3**(02-12,小组1,~7h):冰轮#1 和 #2 燃料传输管线测试。两艘 Block 1 自此转为专职燃料加注。
|
||||||
|
|
||||||
|
**EVA-4**(02-14,小组2,~7h):基地全系统巡检。GHC-05 乘组搭乘吴刚#2 起飞 → LLO 嫦娥 → 返回地球。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2025-03-09 GHC-06 货运发射(CZ-16):广寒04 模块
|
||||||
|
|
||||||
|
```
|
||||||
|
2025-03-09 17:50 CZ-16 发射广寒04 模块至 LEO(180×230 km)
|
||||||
|
2025-03-10 13:20 金蟾#1 在 LEO 对接广寒04,燃料加注
|
||||||
|
2025-03-10 19:05 金蟾#1 执行 TLI
|
||||||
|
2025-03-15 11:30 金蟾#1 近月制动,LLO
|
||||||
|
2025-03-15 16:10 冰轮#3 起飞 → 对接 → 接收广寒04 → 着陆
|
||||||
|
2025-03-16 02:20 冰轮#3 搭载广寒04 着陆东方海
|
||||||
|
```
|
||||||
|
|
||||||
|
### 安装 EVA(3 月)
|
||||||
|
|
||||||
|
**EVA-5**(03-16,小组1,~8h):十字模块卸下,就位于核心舱东北侧扩展区。
|
||||||
|
|
||||||
|
**EVA-6**(03-17,小组2,~8h):温室#2 安装→展开。存储模块安装。
|
||||||
|
|
||||||
|
**EVA-7**(03-18,小组1,~8h):居住舱#3 安装→展开(4 铺位)。堆肥模块安装→连接温室#2 灌溉系统。
|
||||||
|
|
||||||
|
**EVA-8**(03-19,小组2,~8h):加压走道连接十字模块↔核心舱。供电/数据线路接入。基地容量→14 人。
|
||||||
|
|
||||||
|
### 广寒04 模块
|
||||||
|
十字安装模块(4 口)+ 温室#2 + 存储模块 + 居住舱#3(4 人)+ 堆肥模块
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2025-04-06 GHC-07 载人发射(CZ-10E)
|
||||||
|
|
||||||
|
```
|
||||||
|
2025-04-06 01:34 CZ-10E 发射嫦娥(乘组 6 人)
|
||||||
|
2025-04-06 03:10 TLI-1(CZ-10E 二级)+ TLI-2(嫦娥补燃)
|
||||||
|
2025-04-10 19:55 嫦娥近月制动,LLO
|
||||||
|
2025-04-10 21:20 嫦娥对接吴刚#2(LLO 待命)
|
||||||
|
2025-04-11 01:34 吴刚#2 着陆东方海
|
||||||
|
```
|
||||||
|
|
||||||
|
### 前期 EVA(4 月,等待广寒05 货运)
|
||||||
|
|
||||||
|
**EVA-1**(04-12,小组1,~8h):核心舱顶部临时服务舱段拆除——为塔架加压段腾出安装位。太阳能电池板重新安装至电力模块。
|
||||||
|
|
||||||
|
**EVA-2**(04-14,小组2,~7h30m):冰轮编队燃料库存盘点、基地电网负载测试。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2025-04-25 GHC-07 货运发射(CZ-16):广寒05 模块
|
||||||
|
|
||||||
|
```
|
||||||
|
2025-04-25 10:57 CZ-16 发射广寒05 模块至 LEO
|
||||||
|
2025-04-26 06:30 金蟾#2 对接,燃料加注,TLI
|
||||||
|
2025-04-30 22:10 金蟾#2 近月制动,LLO
|
||||||
|
2025-05-01 02:50 冰轮#3 起飞 → 对接 → 接收广寒05
|
||||||
|
2025-05-01 08:30 冰轮#3 搭载广寒05 着陆
|
||||||
|
```
|
||||||
|
|
||||||
|
### 安装 EVA(5 月)
|
||||||
|
|
||||||
|
**EVA-3**(05-01,小组1,~8h):卸货 + 核心舱顶部塔架加压段安装——广寒基地**首次垂直扩建**。
|
||||||
|
|
||||||
|
**EVA-4**(05-02,小组2,~8h):居住舱#4 安装→十字模块剩余节点,展开。
|
||||||
|
|
||||||
|
**EVA-5**(05-03,小组1,~8h):实验舱#2 安装→十字模块最后节点,展开。
|
||||||
|
|
||||||
|
**EVA-6**(05-04,小组2,~7h30m):维生资源存储舱就位。加压走道连接。核反应堆→45%。基地→18 人。
|
||||||
|
|
||||||
|
### 广寒05 模块
|
||||||
|
居住舱#4(4 人)+ 维生资源存储舱 + 实验舱#2 + 核心舱顶部塔架加压段
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2025-05-30 BL-04:冰轮#4 部署(CZ-16)
|
||||||
|
|
||||||
|
```
|
||||||
|
2025-05-30 17:00 CZ-16 发射冰轮#4(Block 2,货运型)— 直接 TLI
|
||||||
|
2025-06-04 12:15 冰轮#4 近月制动,LLO
|
||||||
|
2025-06-04 17:00 冰轮#4 着陆东方海广寒基地
|
||||||
|
```
|
||||||
|
|
||||||
|
由在站 GHC-07 乘组执行着陆后系统检查。冰轮编队达 4 艘:2 Block1(#1#2 燃料加注)+ 2 Block2(#3#4 货运)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2025-06-22 JC-03:金蟾#3 部署(CZ-10E)
|
||||||
|
|
||||||
|
```
|
||||||
|
2025-06-22 21:30 CZ-10E 发射金蟾#3 → LEO 400×400 km
|
||||||
|
```
|
||||||
|
|
||||||
|
金蟾编队达 3 艘,实现并行 LLO↔LEO 物流:一艘在 LLO 装载月面燃料、一艘在 LEO 装载地球上行模块、一艘在途。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2025-07-16 GHC-08:广寒06 货运 + 载人(CZ-16 + CZ-10E 同日发射)
|
||||||
|
|
||||||
|
```
|
||||||
|
2025-07-16 10:06 CZ-16 发射广寒06 模块至 LEO
|
||||||
|
2025-07-16 10:06 CZ-10E 发射嫦娥(乘组 6 人)
|
||||||
|
2025-07-17 05:40 金蟾#1 对接广寒06,燃料加注,TLI
|
||||||
|
2025-07-21 20:40 金蟾#1 近月制动,LLO
|
||||||
|
2025-07-22 01:20 冰轮#3 起飞 → 对接 → 接收广寒06 → 着陆
|
||||||
|
2025-07-22 10:06 嫦娥近月制动,LLO,对接吴刚#3 → 着陆
|
||||||
|
```
|
||||||
|
|
||||||
|
### EVA(7 月)
|
||||||
|
|
||||||
|
**EVA-1**(07-23,小组1,~8h):卸货。核心舱塔架非加压段安装——在塔架加压段上方继续垂直扩建。
|
||||||
|
|
||||||
|
**EVA-2**(07-24,小组2,~8h):十字模块顶部塔架非加压段安装。两套通用通讯模块 + 高增益天线安装于两个塔架顶端。
|
||||||
|
|
||||||
|
**EVA-3**(07-25,小组1,~7h30m):观察舱安装于核心舱塔架顶端——360° 月面全景。
|
||||||
|
|
||||||
|
**EVA-4**(07-26,小组2,~6h):通讯系统激活测试(Ka+S+UHF 全模式)。**吴刚#1(Block 1)退役**——LLO 离轨,受控坠毁于月球背面。
|
||||||
|
|
||||||
|
### 广寒06 模块
|
||||||
|
核心舱顶部塔架观察舱 + 核心舱顶部塔架非加压段 + 十字安装模块顶部塔架非加压段 + 天线 + 顶部塔架通用通讯模块×2
|
||||||
|
|
||||||
|
### 里程碑
|
||||||
|
- ✅ 广寒01~06 全部安装完毕
|
||||||
|
- ✅ 吴刚 Block 1 全退役,编队 3 艘 Block 2
|
||||||
|
- ✅ 金蟾 3 艘并行物流
|
||||||
|
- ✅ 冰轮 4 艘定型
|
||||||
|
- ═══ **长期有人驻守 + 半年轮换 开始** ═══
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2025-08-20 GHC-09 货运发射(CZ-16):十字模块#2
|
||||||
|
|
||||||
|
```
|
||||||
|
2025-08-20 16:10 CZ-16 发射十字模块#2 + 2 段加压走道至 LEO
|
||||||
|
2025-08-21 12:00 金蟾#2 对接,燃料加注,TLI
|
||||||
|
2025-08-26 03:40 金蟾#2 近月制动,LLO
|
||||||
|
2025-08-26 07:20 冰轮#4 起飞 → 对接 → 接收 → 着陆 08-26 12:50
|
||||||
|
```
|
||||||
|
|
||||||
|
十字模块#2 在月面暂存—等待 GHC-09 乘组抵达后安装。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2025-10-06 GHC-10 货运发射(CZ-16):加压月球车
|
||||||
|
|
||||||
|
```
|
||||||
|
2025-10-06 09:16 CZ-16 发射加压月球车 + 2 段加压走道至 LEO
|
||||||
|
2025-10-07 05:00 金蟾#3 对接,燃料加注,TLI
|
||||||
|
2025-10-11 22:30 金蟾#3 近月制动,LLO
|
||||||
|
2025-10-12 03:10 冰轮#3 起飞 → 对接 → 接收 → 着陆 10-12 08:45
|
||||||
|
```
|
||||||
|
|
||||||
|
加压月球车在月面暂存—等待 GHC-10 乘组抵达后激活。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2025-11-10 GHC-09 载人发射(CZ-10E):首次半年轮换
|
||||||
|
|
||||||
|
```
|
||||||
|
2025-11-10 15:19 CZ-10E 发射嫦娥(新乘组 6 人,首次标准半年轮换)
|
||||||
|
2025-11-15 10:20 嫦娥近月制动,LLO,对接吴刚#2
|
||||||
|
2025-11-15 15:19 吴刚#2 着陆东方海
|
||||||
|
```
|
||||||
|
|
||||||
|
### EVA(11 月)
|
||||||
|
|
||||||
|
**EVA-1**(11-16,小组1,~7h):十字模块#2 就位于#1 扩展方向。2 段走道连接 #1↔#2。氦气检漏。
|
||||||
|
|
||||||
|
**EVA-2**(11-17,小组2,~6h):供电/数据接入。在站交接。吴刚#3 留在月面作为紧急逃生载具。
|
||||||
|
|
||||||
|
**EVA-3**(11-18,小组1,~6h):前序乘组搭乘吴刚#2 起飞→嫦娥→返回地球。
|
||||||
|
|
||||||
|
### 里程碑
|
||||||
|
- ✅ 首次标准半年轮换执行完毕
|
||||||
|
- ✅ 基地持续有人驻守开始
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2026-06-09 GHC-10 载人发射(CZ-10E):第二次半年轮换 + 广寒07 完成
|
||||||
|
|
||||||
|
```
|
||||||
|
2026-06-09 06:45 CZ-10E 发射嫦娥(新乘组 6 人,第二次半年轮换)
|
||||||
|
2026-06-14 01:30 嫦娥近月制动,LLO,对接吴刚#3
|
||||||
|
2026-06-14 06:45 吴刚#3 着陆东方海
|
||||||
|
```
|
||||||
|
|
||||||
|
### EVA(2026-06)
|
||||||
|
|
||||||
|
**EVA-1**(06-15,小组1,~8h):加压月球车系统激活——燃料电池+蓄电池、UHF 中继通信、地形匹配导航。短距离测试(~500 m)。
|
||||||
|
|
||||||
|
**EVA-2**(06-16,小组2,~7h30m):剩余 2 段加压走道安装——十字模块#2↔月球车车库。氦气检漏。
|
||||||
|
|
||||||
|
**EVA-3**(06-17,小组1,~7h):加压月球车远程测试(~3 km)。广寒07 全部安装完毕。在站交接。
|
||||||
|
|
||||||
|
**EVA-4**(06-18,小组2,~6h):前序乘组搭乘吴刚#3 起飞→嫦娥→返回地球。
|
||||||
|
|
||||||
|
### 广寒07 模块
|
||||||
|
十字安装模块#2 + 加压月球车 + 4 段加压走道
|
||||||
|
|
||||||
|
### 里程碑
|
||||||
|
- ✅ **广寒基地全部模块安装完毕(广寒01~07)**
|
||||||
|
- ✅ 加压月球车投入使用——月面远程探测能力建立
|
||||||
|
- ✅ 半年轮换常态化运行
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 任务序列全览(按时间)
|
||||||
|
|
||||||
|
```
|
||||||
|
2025-02-02 GHC-06 载人 ── CZ-16A:吴刚#3 首航
|
||||||
|
2025-02-07 冰轮#1 ISRU 拆除,GHC-05 乘组返回
|
||||||
|
2025-03-09 GHC-06 货运 ── CZ-16:广寒04 → 安装 → 14 人
|
||||||
|
2025-04-06 GHC-07 载人 ── CZ-10E
|
||||||
|
2025-04-25 GHC-07 货运 ── CZ-16:广寒05 → 首次垂直扩建 → 18 人
|
||||||
|
2025-05-30 BL-04 ── CZ-16:冰轮#4 着陆
|
||||||
|
2025-06-22 JC-03 ── CZ-10E:金蟾#3 部署
|
||||||
|
2025-07-16 GHC-08 ── CZ-16 + CZ-10E:广寒06 + 吴刚 Block1 退役
|
||||||
|
═══════ 长期有人驻守 + 半年轮换 开始 ═══════
|
||||||
|
2025-08-20 GHC-09 货运 ── CZ-16:十字模块#2
|
||||||
|
2025-10-06 GHC-10 货运 ── CZ-16:加压月球车
|
||||||
|
2025-11-10 GHC-09 载人 ── CZ-10E:首次半年轮换
|
||||||
|
2026-06-09 GHC-10 载人 ── CZ-10E:第二次半年轮换 + 广寒07 完成
|
||||||
|
═══════ 基地扩建完毕,常态化运营 ═══════
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 舰队终点状态
|
||||||
|
|
||||||
|
| 舰型 | 数量 | 组成 | 角色 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| 吴刚 | 3 | 全 Block 2 | 1 艘月面常驻(紧急逃生)、2 艘轮换 |
|
||||||
|
| 冰轮 | 4 | 2 Block1 + 2 Block2 | #1#2 专职燃料加注 / #3#4 货运 |
|
||||||
|
| 金蟾 | 3 | — | 并行 LLO↔LEO 物流环 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*本文档为提案性质。发射窗口由 `scripts/guanghan_windows.py` 计算。CZ-16/16A 合计遵守 30 天最小间隔约束。CZ-10E 独立排期。*
|
||||||
@@ -0,0 +1,277 @@
|
|||||||
|
# KSP Wiki 载具技术参数提取指南
|
||||||
|
|
||||||
|
> **版本**: v1.1
|
||||||
|
> **用途**: 从 KSP `.craft` 文件中提取 wiki 页面所需的全部技术参数
|
||||||
|
> **目标读者**: KSP 技术玩家 & 设定团队成员
|
||||||
|
> **前提**: 读者已了解 KSP craft 文件格式(PART 块结构、坐标系等)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 概述
|
||||||
|
|
||||||
|
本文档定义了创建 KSP Wiki 载具页面时,**可从 craft 文件及游戏内直接获取的技术参数**。这些参数构成 wiki 页面 Infobox 和技术规格章节的核心数据。
|
||||||
|
|
||||||
|
> **不在本文档范围内**: 设计背景、历史叙事、运营故事、任务时间线、安全记录、命名/代号等需人工设定的内容。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 通用技术参数(所有载具类型)
|
||||||
|
|
||||||
|
### 2.1 质量参数
|
||||||
|
|
||||||
|
| # | 参数 | Craft 文件位置 | 提取方法 | 单位 |
|
||||||
|
|---|------|---------------|----------|------|
|
||||||
|
| 1 | **干重** | 每个 `PART` 块的 `mass` | 所有 part 质量求和(含对称副本) | 吨 |
|
||||||
|
| 2 | **满载质量** | `PART` 的 `mass` + `RESOURCE` 的 `amount` × `density` | 干重 + 所有资源质量 | 吨 |
|
||||||
|
| 3 | **推进剂质量** | `RESOURCE` 块 | 各资源 `amount` × `density` 求和 | 吨 |
|
||||||
|
|
||||||
|
**注意**:
|
||||||
|
- `symmetry = N` 的 part 质量需乘以 N
|
||||||
|
- 常见资源密度: `LiquidFuel` = 0.005, `Oxidizer` = 0.005, `MonoPropellant` = 0.008(吨/单位)
|
||||||
|
|
||||||
|
### 2.2 尺寸参数
|
||||||
|
|
||||||
|
| # | 参数 | Craft 文件位置 | 提取方法 | 单位 |
|
||||||
|
|---|------|---------------|----------|------|
|
||||||
|
| 4 | **长度** | `part.position` (x, y, z) | Y 轴方向最大值 - 最小值 | 米 |
|
||||||
|
| 5 | **宽度** | `part.position` | X 轴方向最大值 - 最小值(考虑对称) | 米 |
|
||||||
|
| 6 | **高度** | `part.position` | Z 轴方向最大值 - 最小值 | 米 |
|
||||||
|
|
||||||
|
**坐标系说明**:
|
||||||
|
- KSP craft 文件使用右手坐标系
|
||||||
|
- **Y 轴** = 垂直方向(通常对应载具长度)
|
||||||
|
- **X 轴** = 横向(对应宽度/翼展)
|
||||||
|
- **Z 轴** = 纵深(对应高度)
|
||||||
|
- 实际对应关系取决于载具建造方向,提取后需人工校验
|
||||||
|
|
||||||
|
**重要**: 尺寸为包围盒估算值,需与游戏内实际外观对比校验。
|
||||||
|
|
||||||
|
### 2.3 乘员参数
|
||||||
|
|
||||||
|
| # | 参数 | Craft 文件位置 | 提取方法 |
|
||||||
|
|---|------|---------------|----------|
|
||||||
|
| 7 | **乘员容量** | `MODULE { name = ModuleCommand }` 内的 `CrewCapacity` | 求和所有 command pod |
|
||||||
|
|
||||||
|
### 2.4 推进系统
|
||||||
|
|
||||||
|
| # | 参数 | Craft 文件位置 | 提取方法 |
|
||||||
|
|---|------|---------------|----------|
|
||||||
|
| 8 | **主引擎型号** | `PART` 的 `part` 字段(如 `liquidEngine3`) | 提取引擎 part 名称列表 |
|
||||||
|
| 9 | **主引擎数量** | `PART` 块 + `symmetry` 字段 | 统计引擎 part 数量(含对称副本) |
|
||||||
|
| 10 | **推进剂类型** | `RESOURCE` 块的 `name` | 如 `LiquidFuel`, `Oxidizer`, `MonoPropellant` |
|
||||||
|
| 11 | **推进剂储量** | `RESOURCE` 块的 `amount` | 各资源分别列出 |
|
||||||
|
| 12 | **辅助推进器** | `PART` 名称含 `RCS` | RCS 型号和数量 |
|
||||||
|
| 13 | **各级 Δv** | — | 🔵 使用 MJ/KER 在 VAB 中读取 |
|
||||||
|
| 14 | **推重比 (TWR)** | — | 🔵 使用 MJ/KER 读取(区分海平面/真空) |
|
||||||
|
|
||||||
|
### 2.5 电力系统
|
||||||
|
|
||||||
|
| # | 参数 | Craft 文件位置 | 提取方法 |
|
||||||
|
|---|------|---------------|----------|
|
||||||
|
| 15 | **太阳能板** | `MODULE { name = ModuleDeployableSolarPanel }` 或固定太阳能板 part | 型号和数量 |
|
||||||
|
| 16 | **核发电机** | `MODULE { name = ModuleGenerator }` 或 `ModuleRadioisotopeGenerator` | 型号和数量 |
|
||||||
|
| 17 | **蓄电池** | 含电荷资源 (`ElectricCharge`) 的 part | 型号和容量 |
|
||||||
|
|
||||||
|
### 2.6 结构配置
|
||||||
|
|
||||||
|
| # | 参数 | Craft 文件位置 | 提取方法 |
|
||||||
|
|---|------|---------------|----------|
|
||||||
|
| 18 | **分级配置** | Staging 信息 + 分离装置 part | 各级包含的引擎和分离装置 |
|
||||||
|
| 19 | **外挂/助推器** | `PART` 的 `symmetry` 字段和子节点树 | 通过对称性和 parent 链识别 |
|
||||||
|
| 20 | **着陆装置** | `PART` 名称含 `LandingGear` 或 `LandingLeg` | 型号和数量 |
|
||||||
|
| 21 | **对接口** | `PART` 名称含 `dockingPort` | 型号和数量 |
|
||||||
|
| 22 | **货舱** | `PART` 名称含 `CargoBay` | 型号和尺寸 |
|
||||||
|
| 23 | **整体布局** | Part 树结构 | 🟢 拓扑可提取 → 🔵 需人工描述 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 载具类型专项参数
|
||||||
|
|
||||||
|
### 3.1 航天飞机 (Space Shuttle)
|
||||||
|
|
||||||
|
| # | 参数 | 来源 | 提取方法 |
|
||||||
|
|---|------|------|----------|
|
||||||
|
| S1 | **翼面部件** | 🟢 Craft | 含 `ModuleControlSurface` 或 `ModuleLiftingSurface` 的 part |
|
||||||
|
| S2 | **热防护** | 🟢 Craft | HeatShield part 名称和 ablator 储量 |
|
||||||
|
| S3 | **逃逸系统** | 🟢 Craft | LaunchEscapeSystem part |
|
||||||
|
| S4 | **着陆方式** | 🟢 Craft | 有起落架 = 跑道着陆;无 = 水溅落/其他 |
|
||||||
|
|
||||||
|
### 3.2 母舰 (Mothership)
|
||||||
|
|
||||||
|
| # | 参数 | 来源 | 提取方法 |
|
||||||
|
|---|------|------|----------|
|
||||||
|
| M1 | **环形结构** | 🟢 Craft | 旋转部件 (Gravitron/Centrifuge) part 和半径 |
|
||||||
|
| M2 | **搭载子载具** | 🟢 Craft | 子节点树中的独立载具 part 群组 |
|
||||||
|
| M3 | **对接口配置** | 🟢 Craft | 各对接口类型和位置 |
|
||||||
|
|
||||||
|
### 3.3 空间站 (Space Station)
|
||||||
|
|
||||||
|
| # | 参数 | 来源 | 提取方法 |
|
||||||
|
|---|------|------|----------|
|
||||||
|
| ST1 | **模块数量** | 🟢 Craft | 独立 part 群组(通过分离节点划分) |
|
||||||
|
| ST2 | **对接口总数** | 🟢 Craft | DockingPort part 数量 |
|
||||||
|
|
||||||
|
### 3.4 基地 (Base)
|
||||||
|
|
||||||
|
| # | 参数 | 来源 | 提取方法 |
|
||||||
|
|---|------|------|----------|
|
||||||
|
| B1 | **模块数量** | 🟢 Craft | 独立 part 群组 |
|
||||||
|
| B2 | **移动能力** | 🟢 Craft | 是否有轮毂/履带 part |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Craft 文件提取速查
|
||||||
|
|
||||||
|
### 4.1 关键字段映射表
|
||||||
|
|
||||||
|
| 需要的参数 | Craft 文件字段 | 处理方式 |
|
||||||
|
|-----------|---------------|----------|
|
||||||
|
| 干重 | `PART.mass` | 求和(× symmetry) |
|
||||||
|
| 满载质量 | `PART.mass` + `RESOURCE.amount` × `density` | 求和 |
|
||||||
|
| 尺寸 | `PART.position` (x, y, z) | 包围盒极值差 |
|
||||||
|
| 乘员容量 | `CrewCapacity` (在 ModuleCommand 内) | 求和 |
|
||||||
|
| 引擎型号 | `PART.part` (含 Engine 的 part 名) | 去重列表 |
|
||||||
|
| 引擎数量 | `PART` 计数 × `symmetry` | 求和 |
|
||||||
|
| 推进剂类型 | `RESOURCE.name` | 去重列表 |
|
||||||
|
| 推进剂储量 | `RESOURCE.amount` | 按类型分别列出 |
|
||||||
|
| 太阳能板 | Part 名含 `SolarPanel` | 计数 |
|
||||||
|
| 对接口 | Part 名含 `dockingPort` | 计数 |
|
||||||
|
| 着陆装置 | Part 名含 `LandingGear`/`LandingLeg` | 计数 |
|
||||||
|
| RCS | Part 名含 `RCS` | 计数 |
|
||||||
|
| 分级 | Staging 数据 + 分离装置 part | 分析各级组成 |
|
||||||
|
|
||||||
|
### 4.2 注意事项
|
||||||
|
|
||||||
|
1. **对称性**: `symmetry = N` 表示 N 个副本(含自身),质量/数量计算需乘以 N
|
||||||
|
2. **单位**: 质量 = 吨,距离 = 米
|
||||||
|
3. **子节点**: Part 通过 `parent` 字段形成树状结构,分析拓扑需遍历整棵树
|
||||||
|
4. **Mod 部件**: 非原版 part 名称需对照 mod 文档识别
|
||||||
|
5. **尺寸估算**: 包围盒可能与实际外观有偏差,提取后务必与游戏内截图对比
|
||||||
|
|
||||||
|
### 4.3 推荐工具
|
||||||
|
|
||||||
|
| 工具 | 用途 |
|
||||||
|
|------|------|
|
||||||
|
| **KSP VAB/SPH** | 游戏内直接查看载具参数 |
|
||||||
|
| **MechJeb (MJ)** | 读取 Δv、TWR、各级参数 |
|
||||||
|
| **Kerbal Engineer Redux (KER)** | 实时飞行数据和 VAB 数据 |
|
||||||
|
| **自定义脚本** | Python/Node 脚本批量解析 craft 文件 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 参数完整性检查清单
|
||||||
|
|
||||||
|
提取完成后,确认以下参数已齐全。缺少的项目需标注"未提取"。
|
||||||
|
|
||||||
|
### 所有载具类型
|
||||||
|
|
||||||
|
- [ ] 干重 (吨)
|
||||||
|
- [ ] 满载质量 (吨)
|
||||||
|
- [ ] 长度 (米)
|
||||||
|
- [ ] 宽度/翼展 (米)
|
||||||
|
- [ ] 高度 (米)
|
||||||
|
- [ ] 乘员容量
|
||||||
|
- [ ] 主引擎型号 & 数量
|
||||||
|
- [ ] 推进剂类型 & 储量
|
||||||
|
- [ ] 各级 Δv(MJ/KER 读取值)
|
||||||
|
- [ ] 推重比 TWR(MJ/KER 读取值)
|
||||||
|
- [ ] 发电装置类型
|
||||||
|
- [ ] 着陆装置: 有/无
|
||||||
|
- [ ] 对接口数量
|
||||||
|
|
||||||
|
### 按类型补充
|
||||||
|
|
||||||
|
**航天飞机**:
|
||||||
|
- [ ] 翼面部件
|
||||||
|
- [ ] 热防护 part
|
||||||
|
- [ ] 逃逸系统: 有/无
|
||||||
|
|
||||||
|
**母舰**:
|
||||||
|
- [ ] 旋转结构: 有/无
|
||||||
|
- [ ] 搭载子载具识别
|
||||||
|
- [ ] 对接口配置
|
||||||
|
|
||||||
|
**空间站**:
|
||||||
|
- [ ] 模块划分
|
||||||
|
- [ ] 对接口总数
|
||||||
|
|
||||||
|
**基地**:
|
||||||
|
- [ ] 模块划分
|
||||||
|
- [ ] 移动能力: 有/无
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附录 A: 参数采集表模板
|
||||||
|
|
||||||
|
复制此模板,逐项填写从 craft 文件中提取的参数。
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# [载具英文名称] 技术参数采集表
|
||||||
|
|
||||||
|
## 基本信息
|
||||||
|
- Craft 文件名:
|
||||||
|
- Craft 文件路径:
|
||||||
|
- 使用的 Mod (若有):
|
||||||
|
|
||||||
|
## 质量
|
||||||
|
- 干重 (吨):
|
||||||
|
- 推进剂质量 (吨):
|
||||||
|
- 满载质量 (吨):
|
||||||
|
|
||||||
|
## 尺寸 (估算值,需游戏内校验)
|
||||||
|
- 长度 (米):
|
||||||
|
- 宽度 (米):
|
||||||
|
- 高度 (米):
|
||||||
|
|
||||||
|
## 乘员
|
||||||
|
- 乘员容量:
|
||||||
|
|
||||||
|
## 推进系统
|
||||||
|
- 主引擎型号:
|
||||||
|
- 主引擎数量:
|
||||||
|
- 推进剂类型:
|
||||||
|
- 推进剂储量:
|
||||||
|
- 各级 Δv (MJ/KER):
|
||||||
|
- 第一级:
|
||||||
|
- 第二级:
|
||||||
|
- ...
|
||||||
|
- 推重比 TWR (真空):
|
||||||
|
- RCS 型号:
|
||||||
|
- RCS 数量:
|
||||||
|
|
||||||
|
## 电力系统
|
||||||
|
- 太阳能板: 型号 × 数量
|
||||||
|
- 核发电机: 型号 × 数量
|
||||||
|
- 蓄电池: 型号 × 数量
|
||||||
|
|
||||||
|
## 结构配置
|
||||||
|
- 分级数:
|
||||||
|
- 助推器: 有/无,数量:
|
||||||
|
- 着陆装置: 有/无,型号:
|
||||||
|
- 对接口: 数量
|
||||||
|
- 货舱: 有/无
|
||||||
|
|
||||||
|
## 航天飞机专项
|
||||||
|
- 翼面部件:
|
||||||
|
- 热防护 part:
|
||||||
|
- 逃逸系统: 有/无
|
||||||
|
|
||||||
|
## 母舰专项
|
||||||
|
- 旋转结构: 有/无
|
||||||
|
- 搭载子载具:
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附录 B: 已有 Wiki 页面技术参数参考
|
||||||
|
|
||||||
|
以下已有页面可作为参数填写格式的参考(查看其 Infobox 中的技术参数部分):
|
||||||
|
|
||||||
|
| 载具 | 文件 | 参考价值 |
|
||||||
|
|------|------|---------|
|
||||||
|
| Vulture Shuttle | `data/wiki/vulture_shuttle_zh.html` | 航天飞机 Infobox 完整范例 |
|
||||||
|
| Echo Shuttle | `data/wiki/echo_shuttle_zh.html` | 轻型航天飞机参数格式 |
|
||||||
|
| Enterprise Shuttle | `data/wiki/enterprise_shuttle_zh.html` | 中型航天飞机参数格式 |
|
||||||
|
| Xihe-class | `data/wiki/xihe_mothership_zh.html` | 母舰级别 Infobox 范例 |
|
||||||
|
| XH-01 Xihe | `data/wiki/xh01_xihe_zh.html` | 单舰 Infobox 范例 |
|
||||||
|
| ST-01 Wanxingyuan | `data/wiki/st01_wanxingyuan_zh.html` | 复杂母舰参数范例 |
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""广寒计划发射窗口计算
|
||||||
|
|
||||||
|
广寒基地往返标准 LLO,每月有 2 个标准窗口。
|
||||||
|
地月转移耗时 5 天。给定任意时间,计算最近的地球出发发射窗口
|
||||||
|
及对应的月球着陆窗口。
|
||||||
|
"""
|
||||||
|
|
||||||
|
import math
|
||||||
|
import sys
|
||||||
|
from datetime import datetime, timedelta, timezone
|
||||||
|
|
||||||
|
MOON_PERIOD = timedelta(days=27.32166) # 月球自转周期
|
||||||
|
TRANSIT_DAYS = timedelta(days=5) # 地月转移耗时
|
||||||
|
|
||||||
|
# 参考着陆窗口(UTC)—— 发射窗口 = 着陆窗口 − 5 天地月转移
|
||||||
|
# 基于 2024 年 10 月精确窗口校准
|
||||||
|
REF_LANDING_A = datetime(2024, 10, 21, 4, 55, tzinfo=timezone.utc)
|
||||||
|
REF_LANDING_B = datetime(2024, 10, 29, 3, 15, tzinfo=timezone.utc)
|
||||||
|
REF_LAUNCH_A = REF_LANDING_A - TRANSIT_DAYS
|
||||||
|
REF_LAUNCH_B = REF_LANDING_B - TRANSIT_DAYS
|
||||||
|
|
||||||
|
|
||||||
|
def parse_dt(s: str) -> datetime:
|
||||||
|
"""解析用户输入的日期时间字符串,自动补全缺失部分。"""
|
||||||
|
s = s.strip()
|
||||||
|
formats = [
|
||||||
|
"%Y-%m-%d %H:%M",
|
||||||
|
"%Y-%m-%d %H",
|
||||||
|
"%Y-%m-%d",
|
||||||
|
"%Y/%m/%d %H:%M",
|
||||||
|
"%Y/%m/%d %H",
|
||||||
|
"%Y/%m/%d",
|
||||||
|
]
|
||||||
|
for fmt in formats:
|
||||||
|
try:
|
||||||
|
return datetime.strptime(s, fmt).replace(tzinfo=timezone.utc)
|
||||||
|
except ValueError:
|
||||||
|
continue
|
||||||
|
raise ValueError(f"无法解析日期: {s}(支持格式: YYYY-MM-DD HH:MM 或 YYYY/MM/DD)")
|
||||||
|
|
||||||
|
|
||||||
|
def next_occurrences(ref: datetime, period: timedelta, after: datetime, count: int = 3):
|
||||||
|
"""计算从 after 之后最近的 count 个窗口(以 ref 为相位零点)。"""
|
||||||
|
n = math.floor((after - ref) / period) # 已完成周期数(floor确保负数时正确)
|
||||||
|
results = []
|
||||||
|
for i in range(1, count + 1):
|
||||||
|
results.append(ref + (n + i) * period)
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
def guanghan_windows(target: datetime, count: int = 4):
|
||||||
|
"""返回最近 count 个广寒发射/着陆窗口。
|
||||||
|
|
||||||
|
以着陆窗口为相位零点,发射窗口 = 着陆窗口 − 5 天地月转移。
|
||||||
|
"""
|
||||||
|
landing_a = next_occurrences(REF_LANDING_A, MOON_PERIOD, target, count)
|
||||||
|
landing_b = next_occurrences(REF_LANDING_B, MOON_PERIOD, target, count)
|
||||||
|
|
||||||
|
# 合并着陆窗口,去重排序
|
||||||
|
all_landings = sorted(set(landing_a + landing_b))
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
lines.append(f"查询时间: {target.strftime('%Y-%m-%d %H:%M UTC')}")
|
||||||
|
lines.append(f"参考着陆窗 A: {REF_LANDING_A.strftime('%Y-%m-%d %H:%M UTC')}")
|
||||||
|
lines.append(f"参考着陆窗 B: {REF_LANDING_B.strftime('%Y-%m-%d %H:%M UTC')}")
|
||||||
|
lines.append(f"月球周期: {MOON_PERIOD.days}.{MOON_PERIOD.seconds/3600:.2f} 天")
|
||||||
|
lines.append(f"地月转移: 5 天")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
header = f"{'#':<4} {'发射 (UTC)':<22} {'着陆 (UTC)':<22} {'距现在':>10}"
|
||||||
|
lines.append(header)
|
||||||
|
lines.append("-" * len(header))
|
||||||
|
|
||||||
|
for i, landing in enumerate(all_landings[:count], 1):
|
||||||
|
launch = landing - TRANSIT_DAYS
|
||||||
|
delta = launch - target
|
||||||
|
if delta.days >= 0:
|
||||||
|
delta_str = f"{delta.days}d {delta.seconds // 3600}h"
|
||||||
|
else:
|
||||||
|
delta_str = f"已过"
|
||||||
|
|
||||||
|
lines.append(f"{i:<4} {launch.strftime('%Y-%m-%d %H:%M'):<22} {landing.strftime('%Y-%m-%d %H:%M'):<22} {delta_str:>10}")
|
||||||
|
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("用法: python guanghan_windows.py <日期时间>")
|
||||||
|
print("示例: python guanghan_windows.py '2024-07-20'")
|
||||||
|
print(" python guanghan_windows.py '2024-08-15 12:00'")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
target = parse_dt(sys.argv[1])
|
||||||
|
print(guanghan_windows(target))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Inject lightbox CSS and JS into all Guanghan wiki pages."""
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
LIGHTBOX_CSS = """
|
||||||
|
.wiki-article img[data-wiki-asset] { cursor: zoom-in; }
|
||||||
|
.wiki-image-lightbox { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; padding: 24px; background: rgba(32,33,34,0.84); z-index: 10000; box-sizing: border-box; }
|
||||||
|
.wiki-image-lightbox[hidden] { display: none; }
|
||||||
|
.wiki-image-lightbox-panel { position: relative; width: min(1120px, 96vw); max-height: 92vh; overflow: auto; margin: 0; padding: 10px; border: 1px solid #a2a9b1; background: #fff; box-shadow: 0 12px 38px rgba(0,0,0,0.35); box-sizing: border-box; }
|
||||||
|
.wiki-image-lightbox-panel img { display: block; width: 100%; height: auto; max-height: 82vh; object-fit: contain; background: #000; }
|
||||||
|
.wiki-image-lightbox-close { position: sticky; top: 0; float: right; width: 30px; height: 30px; margin: -2px -2px 8px 10px; border: 1px solid #a2a9b1; background: #eaecf0; color: #202122; font-weight: bold; line-height: 26px; cursor: pointer; }
|
||||||
|
.wiki-image-lightbox-close:hover, .wiki-image-lightbox-close:focus { background: #fff; }
|
||||||
|
body.wiki-image-lightbox-open { overflow: hidden; }
|
||||||
|
@media (max-width: 820px) { .wiki-image-lightbox { padding: 12px; } .wiki-image-lightbox-panel { width: 98vw; max-height: 94vh; } }"""
|
||||||
|
|
||||||
|
LIGHTBOX_JS = """<script>
|
||||||
|
(function () {
|
||||||
|
function ready(fn) {
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', fn, { once: true });
|
||||||
|
} else {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function captionFor(image) {
|
||||||
|
var container = image.closest('figure, td, tr, .infobox-image, .gallery-item');
|
||||||
|
if (!container) {
|
||||||
|
return image.alt || '';
|
||||||
|
}
|
||||||
|
var caption = container.querySelector('.thumbcaption');
|
||||||
|
return caption ? caption.textContent.trim() : (image.alt || '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function install(article) {
|
||||||
|
if (!article || article.dataset.lightboxReady === '1') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
article.dataset.lightboxReady = '1';
|
||||||
|
|
||||||
|
var overlay = document.createElement('div');
|
||||||
|
overlay.className = 'wiki-image-lightbox';
|
||||||
|
overlay.hidden = true;
|
||||||
|
overlay.innerHTML = '<figure class="wiki-image-lightbox-panel" role="dialog" aria-modal="true"><button class="wiki-image-lightbox-close" type="button" aria-label="Close image preview">x</button><img alt=""><figcaption class="thumbcaption"></figcaption></figure>';
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
|
||||||
|
var previewImage = overlay.querySelector('img');
|
||||||
|
var previewCaption = overlay.querySelector('figcaption');
|
||||||
|
var closeButton = overlay.querySelector('.wiki-image-lightbox-close');
|
||||||
|
|
||||||
|
function closePreview() {
|
||||||
|
overlay.hidden = true;
|
||||||
|
previewImage.removeAttribute('src');
|
||||||
|
previewCaption.textContent = '';
|
||||||
|
document.body.classList.remove('wiki-image-lightbox-open');
|
||||||
|
}
|
||||||
|
|
||||||
|
function openPreview(image, event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
if (event.stopImmediatePropagation) {
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
}
|
||||||
|
previewImage.src = image.currentSrc || image.src;
|
||||||
|
previewImage.alt = image.alt || '';
|
||||||
|
previewCaption.textContent = captionFor(image);
|
||||||
|
overlay.hidden = false;
|
||||||
|
document.body.classList.add('wiki-image-lightbox-open');
|
||||||
|
closeButton.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
article.querySelectorAll('img[data-wiki-asset]').forEach(function (image) {
|
||||||
|
if (image.dataset.lightboxBound === '1') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
image.dataset.lightboxBound = '1';
|
||||||
|
image.addEventListener('click', function (event) {
|
||||||
|
openPreview(image, event);
|
||||||
|
}, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
article.addEventListener('click', function (event) {
|
||||||
|
var image = event.target.closest && event.target.closest('img[data-wiki-asset]');
|
||||||
|
if (!image || !article.contains(image) || image.closest('.wiki-image-lightbox')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
openPreview(image, event);
|
||||||
|
});
|
||||||
|
|
||||||
|
closeButton.addEventListener('click', closePreview);
|
||||||
|
overlay.addEventListener('click', function (event) {
|
||||||
|
if (event.target === overlay) {
|
||||||
|
closePreview();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
document.addEventListener('keydown', function (event) {
|
||||||
|
if (event.key === 'Escape' && !overlay.hidden) {
|
||||||
|
closePreview();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function installAll() {
|
||||||
|
document.querySelectorAll('.wiki-article, .vulture-article').forEach(install);
|
||||||
|
}
|
||||||
|
|
||||||
|
ready(function () {
|
||||||
|
installAll();
|
||||||
|
if (window.MutationObserver) {
|
||||||
|
var observer = new MutationObserver(installAll);
|
||||||
|
observer.observe(document.body, { childList: true, subtree: true });
|
||||||
|
}
|
||||||
|
window.setTimeout(installAll, 500);
|
||||||
|
window.setTimeout(installAll, 1500);
|
||||||
|
window.setTimeout(installAll, 3000);
|
||||||
|
});
|
||||||
|
}());
|
||||||
|
</script>"""
|
||||||
|
|
||||||
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
WIKI_DIR = os.path.join(BASE_DIR, 'data', 'wiki')
|
||||||
|
|
||||||
|
files = [
|
||||||
|
'guanghan_bl01_zh.html', 'guanghan_bl02_zh.html', 'guanghan_bl03_zh.html',
|
||||||
|
'guanghan_ghc01_zh.html', 'guanghan_ghc02_zh.html', 'guanghan_ghc03_zh.html',
|
||||||
|
'guanghan_ghc04_zh.html', 'guanghan_jc01_zh.html',
|
||||||
|
'guanghan_bl01_gallery_zh.html', 'guanghan_bl02_gallery_zh.html',
|
||||||
|
'guanghan_bl03_gallery_zh.html', 'guanghan_ghc01_gallery_zh.html',
|
||||||
|
'guanghan_ghc02_gallery_zh.html', 'guanghan_ghc03_gallery_zh.html',
|
||||||
|
'guanghan_ghc04_gallery_zh.html', 'guanghan_jc01_gallery_zh.html',
|
||||||
|
]
|
||||||
|
|
||||||
|
for fname in files:
|
||||||
|
fpath = os.path.join(WIKI_DIR, fname)
|
||||||
|
with open(fpath, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
if 'wiki-image-lightbox' in content:
|
||||||
|
print(f'SKIP (already done): {fname}')
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Inject CSS before </style>
|
||||||
|
content = content.replace('</style>', LIGHTBOX_CSS + '\n</style>')
|
||||||
|
|
||||||
|
# Inject JS before </article>
|
||||||
|
content = content.replace('</article>', LIGHTBOX_JS + '\n</article>')
|
||||||
|
|
||||||
|
with open(fpath, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(content)
|
||||||
|
print(f'DONE: {fname}')
|
||||||
|
|
||||||
|
print('=== Injection complete ===')
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
cd "d:/My Coding Project/KSP_Project"
|
||||||
|
|
||||||
|
# Lightbox CSS to add before </style>
|
||||||
|
LB_CSS='
|
||||||
|
.wiki-article img[data-wiki-asset] { cursor: zoom-in; }
|
||||||
|
.wiki-image-lightbox { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; padding: 24px; background: rgba(32,33,34,0.84); z-index: 10000; box-sizing: border-box; }
|
||||||
|
.wiki-image-lightbox[hidden] { display: none; }
|
||||||
|
.wiki-image-lightbox-panel { position: relative; width: min(1120px, 96vw); max-height: 92vh; overflow: auto; margin: 0; padding: 10px; border: 1px solid #a2a9b1; background: #fff; box-shadow: 0 12px 38px rgba(0,0,0,0.35); box-sizing: border-box; }
|
||||||
|
.wiki-image-lightbox-panel img { display: block; width: 100%; height: auto; max-height: 82vh; object-fit: contain; background: #000; }
|
||||||
|
.wiki-image-lightbox-close { position: sticky; top: 0; float: right; width: 30px; height: 30px; margin: -2px -2px 8px 10px; border: 1px solid #a2a9b1; background: #eaecf0; color: #202122; font-weight: bold; line-height: 26px; cursor: pointer; }
|
||||||
|
.wiki-image-lightbox-close:hover, .wiki-image-lightbox-close:focus { background: #fff; }
|
||||||
|
body.wiki-image-lightbox-open { overflow: hidden; }
|
||||||
|
@media (max-width: 820px) { .wiki-image-lightbox { padding: 12px; } .wiki-image-lightbox-panel { width: 98vw; max-height: 94vh; } }'
|
||||||
|
|
||||||
|
for f in data/wiki/guanghan_bl01_zh.html data/wiki/guanghan_bl02_zh.html data/wiki/guanghan_bl03_zh.html data/wiki/guanghan_ghc01_zh.html data/wiki/guanghan_ghc02_zh.html data/wiki/guanghan_ghc03_zh.html data/wiki/guanghan_ghc04_zh.html data/wiki/guanghan_jc01_zh.html data/wiki/guanghan_bl01_gallery_zh.html data/wiki/guanghan_bl02_gallery_zh.html data/wiki/guanghan_bl03_gallery_zh.html data/wiki/guanghan_ghc01_gallery_zh.html data/wiki/guanghan_ghc02_gallery_zh.html data/wiki/guanghan_ghc03_gallery_zh.html data/wiki/guanghan_ghc04_gallery_zh.html data/wiki/guanghan_jc01_gallery_zh.html; do
|
||||||
|
if grep -q 'wiki-image-lightbox' "$f" 2>/dev/null; then
|
||||||
|
echo "SKIP (already done): $f"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
# Add CSS before </style>
|
||||||
|
sed -i "s|</style>|${LB_CSS}\n</style>|" "$f"
|
||||||
|
echo "DONE: $f"
|
||||||
|
done
|
||||||
|
echo "=== CSS injection complete ==="
|
||||||
Reference in New Issue
Block a user