Files
insar-management-system-v2/docs/DEPLOYMENT.md
T

968 lines
43 KiB
Markdown
Raw 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.
# InSAR 自动化管理与智能评估系统 - 部署与使用说明
本文件为本项目主中文文档,整合了产品说明、技术架构、业务流程、部署与启动、数据库与授权等内容。
补充专题文档见:`docs/TODO.md``docs/RADAR_PREVIEW_SCHEME_B.md`
---
## 1. 产品概述
本系统是一套深度集成 **IDL/ENVI SARscape** 的专业级 InSAR 数据管理与智能分析平台,聚焦地质灾害监测领域,解决大规模雷达影像处理流程繁琐、数据关联困难、结果解译依赖人工等问题。
通过“Web 化管理 + 自动化引擎 + AI 智能诊断”的三位一体架构,实现从原始 SAR 影像入库到生成形变诊断报告的全生命周期自动化管理。
---
## 2. 核心优势
- **核心流程自动化**:覆盖数据监控、精轨关联、干涉配对、自动化处理引导与结果发布(当前扫描调度默认手动触发)。
- **高精度空间引擎**:凸包算法 + 仿射变换,支持亚像素级 Footprint 提取与空间关联。
- **AI 辅助决策**:集成随机森林质量评估模型与 VLM 视觉大模型,给出专家级解译建议。
- **工业级稳定性**:针对 Windows Server 环境优化,支持 GB 级超大影像处理。
---
## 3. 技术架构
- **管理层 (Web Interface)**React + Vite + Leaflet(支持离线多级细节加载)
- **逻辑层 (Service Layer)**FastAPI 异步框架,集成 PostgreSQL + PostGIS
- **空间引擎 (Spatial Engine)**PostGIS 原生计算 + GeoAlchemy2 + Rasterio
- **AI 引擎 (Intelligence)**Scikit-learn + 本地 Ollama VLM
- **计算引擎 (Compute)**IDL 8.8 / ENVI 5.6SARscape 5.6+
---
## 4. 业务流程指南
### 4.1 数据资产监控
当前系统默认采用 **Manual-only(手动触发)** 扫描模式,不启用后台定时守护任务。
可通过前端“立即扫描”或接口 `POST /api/monitor/run-now` 触发扫描;扫描内部仍采用增量策略以降低系统负载。
**D-InSAR 结果扫描说明(重要):**
当前 D-InSAR 结果扫描为**全量遍历 + 仅新增入库**。
即:每次扫描都会遍历所有 `.hdr` 文件,但数据库只写入“新发现”的结果记录,以保证准确性和稳定性。
扫描任务的进度条基于**实际遍历数量与处理数量**计算,前端显示为真实进度。
数据列表已支持“影像信息”按钮,可查看影像基础元数据(卫星/日期/模式/极化/精轨等)。
影像元数据解析已扩展:优先从 XML 获取成像模式/极化/轨道方向,并补充卫星模式、接收站代号、圈号、景中心经纬度、采集时间、产品类型/级别、唯一标识等字段用于展示。
源数据预览缓存接口:`GET /api/radar-data/{data_id}/thumb`(首次请求若无缓存会自动生成)。
**源影像预览(Scheme B:后端预纠正缓存)**
系统已接入双层缓存:
- `backend/image_cache/radar_geo/`:地理纠正后的主缓存(前端优先使用)
- `backend/image_cache/radar_raw/`:原图 WebP 回退缓存
**D-InSAR 结果缓存(标准目录)**
- `backend/image_cache/dinsar/`D-InSAR 结果可视化缓存目录
- 文件命名:`ID_{id}_{name}.webp`
- 清单文件:`backend/image_cache/dinsar/cache_manifest.json`
**一致性检测(统计面板)**
- `GET /api/statistics` 已新增一致性字段,用于校验“数据库记录 vs 实际缓存文件 vs XML 读取结果”。
- 重点包含:
- D-InSAR`db_cached_but_file_missing_count``db_uncached_but_file_exists_count``manifest_missing_file_count`
- 源影像预览:`db_ready_but_cache_missing_count``preview_missing_count`
- XML`xml_detected_but_unparsed_count``xml_missing_count`
- 前端「数据统计仪表盘」会直接显示异常数量并高亮提示,便于运维快速定位问题。
新增接口:
- `GET /api/radar-data/{id}/preview-status`:查询单条源影像预览缓存状态
- `POST /api/radar-data/{id}/rebuild-preview-cache`:管理员强制重建该影像预览缓存
- `GET /api/radar-data?limit=500&offset=0`:分页获取源数据列表(单次最多 2000 条)
- `POST /api/radar-data/search`:源数据分页检索(支持详情字段筛选 + 行政区/上传SHP空间筛选)
- `GET /api/radar-data/search/options`:获取源数据检索下拉选项(来自数据库去重值)
- `GET /api/dinsar-results?limit=500&offset=0`:分页获取 D-InSAR 结果列表(单次最多 2000 条)
- `GET /api/radar-data/imaging-dates`:获取所有可用成像日期(用于配对起始日期下拉框)
- `GET /api/statistics`:默认返回缓存快照;管理员可用 `GET /api/statistics?fresh=true` 强制重算
`/api/radar-data/search` 说明:
- 权限:管理员与只读账号均可调用(只读安全查询接口)。
- 筛选字段:可按卫星、成像时间范围、模式/极化/产品元数据等详情字段检索。
- 空间筛选:支持 `region_tree_id`(复用行政区)或上传 AOI 文件(`.shp`/GeoJSON)。
- 分页性能:首次 AOI 查询会返回 `aoi_token`,后续翻页可仅携带 token,无需重复上传文件。
- 前端交互:检索字段采用“全下拉可选”,避免手工输入导致的筛选误差。
分页接口响应结构(`/api/radar-data``/api/dinsar-results` 一致):
```json
{
"items": [],
"total": 12345,
"limit": 200,
"offset": 0,
"has_more": true
}
```
前端分页说明:
- 「数据列表」与「D-InSAR 结果」均支持上一页/下一页、每页条数切换(50/100/200/500)与页码跳转。
- 前端默认每页 200 条,避免一次性加载全量数据导致页面和地图卡顿。
- 「数据列表」改为“先检索后展示”:系统启动后不自动加载源数据,需点击“搜索”或“搜索全部源数据”后才显示列表与分页结果。
- 当检索条件变更并再次执行搜索时,前端会先清空旧结果再渲染新结果,避免“旧页数据残留”造成误判。
- 异常/堆栈文本默认不参与界面翻译(e.g. `NoneType object is not callable``Traceback`),保持原始语言以避免日志或异常信息被误替换。
新增环境变量(可选):
```env
RADAR_GEO_CACHE_WORKERS=2
RADAR_GEO_CACHE_VERSION=b1
RADAR_GEO_CACHE_QUALITY=84
RADAR_PREVIEW_BUILD_ON_DEMAND=true
```
说明:
- `thumb` 接口优先返回 `radar_geo`,失败时自动回退 `radar_raw`
- 扫描任务会增量构建 `radar_geo`,并维护 `radar_raw` 作为兜底。
- 如纠正逻辑升级,提升 `RADAR_GEO_CACHE_VERSION` 可触发重建。
- 纠正方向判定优先使用 XML 的 `sceneCornerCoord/refRow/refColumn` 建立“像素角 ↔ 地理角”映射,可显著减少左右/上下方向错误。
### 4.2 任务分发与处理
系统生成处理清单对接 IDL 自动化脚本,用户可在 Web 端一键启动本地 IDL 工作站,实现“云端规划,本地计算”。
### 4.3 智能诊断报告
AI 模块结合影像范围内的已知灾害点生成 Markdown 报告,涵盖:活动性评估、隐患搜寻、风险评级与处置建议。
---
## 5. 核心算法与机制概览
为保持文档完整性,以下为算法专题的简要说明(不再拆分子文档):
- **智能任务规划与贪心优化**:多维约束模型、覆盖多样性惩罚与任务筛选策略。
- **空间几何与极速 Footprint**:降采样探测 + 凸包生成,结合拓扑简化提升效率。
- **AI 诊断与图像处理**:百分比截断拉伸、质量评估特征与自动裁剪策略。
---
## 6. 环境与依赖
- **OS**Windows Server 2019+(推荐)
- **数据库**PostgreSQL 14+ + PostGIS
- **Python**:推荐 Conda 环境(本项目 environment.yml 已固定为 Python 3.10
- **Nginx**:用于前端静态资源与反向代理(推荐)
- **Node.js**:仅构建前端时需要
- **IDL/ENVI**:仅启用 IDL 自动化时需要
---
## 7. 离线 Python 环境(推荐:conda-pack
### 7.1 开发机(有外网)
```powershell
conda env create -f environment.yml
conda activate InSAR
```
如需授权功能,请确保安装 cryptography
```powershell
pip install cryptography
```
如需打包授权 GUI
```powershell
pip install pyinstaller
```
打包环境:
```powershell
conda install -n base conda-pack
conda pack -n InSAR -o insar_env.tar.gz
```
`insar_env.tar.gz` 拷贝到服务器。
### 7.2 服务器(离线)
解压到目标目录(示例:`C:\envs\InSAR`):
```powershell
mkdir C:\envs\InSAR
tar -xzf insar_env.tar.gz -C C:\envs\InSAR
C:\envs\InSAR\Scripts\conda-unpack.exe
```
如果没有 `tar`,可使用 7-Zip 解压。
`.env` 中配置:
```
PYTHON_PATH=C:\envs\InSAR\python.exe
```
`PYTHON_PATH` 也支持命令名(如 `python`),`scripts/start_app.ps1` 会通过 `Get-Command` 解析真实可执行文件路径。
若使用 Conda,建议先激活 `InSAR` 环境后再启动,或直接填入该环境的 `python.exe` 绝对路径。
也可使用 Conda 原生模式(推荐):
```
CONDA_EXE=D:\anaconda3\Scripts\conda.exe
CONDA_ENV_NAME=InSAR
```
`CONDA_ENV_NAME` 非空时,`scripts/start_app.ps1` 会优先使用
`CONDA_EXE` 定位目标环境并解析其 `python.exe`,随后使用该解释器执行数据库检查、初始化、后端与 Worker 启动流程(避免并发 `conda run` 稳定性问题)。
**不建议直接复制 venv**,二进制依赖容易失效。
---
## 8. 数据库准备
### 8.1 创建数据库
```powershell
psql -U postgres -h localhost -p 5432
CREATE DATABASE insar_management;
\q
```
### 8.2 启用 PostGIS
```powershell
psql -U postgres -h localhost -p 5432 -d insar_management
CREATE EXTENSION IF NOT EXISTS postgis;
\q
```
### 8.3 配置连接并检测
`.env` 中设置:
```
DATABASE_URL=postgresql+asyncpg://user:pass@host:5432/insar_management
```
手动检查连接:
```powershell
D:\anaconda3\Scripts\conda.exe run -n InSAR python scripts/check_db_connection.py
```
---
## 9. 授权(离线)
启动授权管理工具:
```powershell
D:\anaconda3\Scripts\conda.exe run -n InSAR python scripts/license_manager_gui.py
```
使用流程:
1) 选择 `.env` 路径
2) 输入到期时间(UTC,格式:`YYYY-MM-DD HH:MM:SS`,留空默认 1 年)
3) 点击“生成/续期授权”
4) 自动写入 `.env` 中的 `LICENSE_SECRET` / `LICENSE_PUBLIC_KEY`
5) 生成 `backend\license\license.lic``license_private_key.txt`
说明:
- `license_private_key.txt` 请妥善保存(用于续期)。
- 服务器只需要公钥与授权文件,不要部署私钥。
- 建议仅在离线管理机保存私钥文件,避免在业务服务器落盘或备份私钥。
- 离线授权属于本地合规校验机制:可显著提高误用门槛,但不等同于“对拥有服务器管理员权限场景”的绝对防篡改。
授权相关接口:
```
/api/license/status
/api/license/upload (仅管理员可调用)
/api/license/refresh (仅管理员可调用)
```
返回约束(安全脱敏):
- `GET /api/license/status` 默认仅返回 `ok``reason``expires_at`
- 当请求携带管理员会话时,`GET /api/license/status` 会额外返回调试字段(如 `fingerprint``license_path`)。
---
## 10. 关键配置(.env
常用参数示例:
```
# 服务显示地址(用于启动日志与前端展示)
SERVER_HOST=192.168.1.100
# 后端端口(示例使用 18000,避免与常见本机服务冲突)
PORT=18000
# 前端开发模式代理目标(仅 npm run dev 使用)
VITE_BACKEND_TARGET=http://localhost:18000
# Python / Nginx 路径
PYTHON_PATH=C:\envs\InSAR\python.exe
CONDA_EXE=D:\anaconda3\Scripts\conda.exe
CONDA_ENV_NAME=InSAR
NGINX_PATH=C:\nginx-1.29.4\nginx.exe
# IDL / ENVI 路径与 worker 管理目录
IDL_EXECUTABLE=C:\Program Files\Harris\ENVI56\IDL88\bin\bin.x86_64\idl.exe
IDL_WORKBENCH_PATH=C:\Program Files\Harris\ENVI56\IDL88\bin\bin.x86_64\idlde.exe
IDL_WORKER_SCRIPT_SOURCE_DIR=Z:\Code\Insar_management_system_v2\IDL\origin
IDL_WORKER_SCRIPT_DIR=Z:\Code\Insar_management_system_v2\IDL\worker_managed
IDL_WORKER_RUNTIME_DIR=Z:\Code\Insar_management_system_v2\backend\runtime\idl_worker
IDL_WORKER_DEFAULT_TIMEOUT_SECONDS=14400
IDL_WORKER_MAX_TIMEOUT_SECONDS=43200
IDL_WORKER_TEMP_DIRECTORY=D:\Sarscape_IDL_Area
# IDL worker 默认任务参数(可被 API 请求体覆盖)
IDL_IMPORT_ROOT_DIR=
IDL_IMPORT_NUM_TO_PROCESS=0
IDL_DINSAR_ROOT_DIR=
IDL_DINSAR_DEM_BASE_FILE=
IDL_DINSAR_NUM_TO_PROCESS=0
IDL_DINSAR_TARGET_GROUND_RESOLUTION_M=10.0
IDL_DINSAR_FILTER_METHOD=GOLDSTEIN
IDL_DINSAR_UNWRAP_COH_THRESHOLD=0.05
IDL_DINSAR_GCP_COH_THRESHOLD=0.7
IDL_DINSAR_GCP_NUMBER=100
IDL_DINSAR_GEOCODING_COH_THRESHOLD=0.0
IDL_DINSAR_GEOCODING_PIXEL_SIZE_M=10.0
# 授权
LICENSE_SECRET=...
LICENSE_PUBLIC_KEY=...
LICENSE_PATH=...\backend\license\license.lic
LICENSE_STATE_PATH=...\backend\license\license_state.json
MAX_LICENSE_UPLOAD_BYTES=1048576
# 鉴权(Session + Cookie
INIT_ADMIN_USERNAME=admin
INIT_ADMIN_PASSWORD=<REQUIRED_STRONG_PASSWORD>
INIT_ADMIN_RESET_PASSWORD=false
SESSION_TTL_HOURS=12
AUTH_SESSION_COOKIE_NAME=ims_session
AUTH_COOKIE_SAMESITE=Lax
AUTH_COOKIE_SECURE=false
AUTH_LOGIN_MAX_FAILURES=5
AUTH_LOGIN_WINDOW_SECONDS=900
AUTH_LOGIN_LOCK_SECONDS=900
AUTH_LOGIN_CLEANUP_INTERVAL_SECONDS=300
# AOI 上传限流
AOI_UPLOAD_MAX_FILES=10
AOI_UPLOAD_MAX_SINGLE_FILE_BYTES=20971520
AOI_UPLOAD_MAX_TOTAL_BYTES=104857600
# 扫描请求边界
MAX_SCAN_DIRECTORY_COUNT=64
MAX_SCAN_PATH_LENGTH=2048
# 高频列表查询边界与超时
LIST_QUERY_MAX_LIMIT=2000
LIST_QUERY_MAX_OFFSET=200000
LIST_QUERY_MAX_WINDOW=202000
LIST_QUERY_TIMEOUT_MS=20000
RADAR_SEARCH_OPTIONS_MAX_VALUES=5000
RADAR_IMAGING_DATES_MAX_VALUES=5000
# 队列入队边界(防止异常大 payload 冲击数据库)
JOB_QUEUE_MAX_PAYLOAD_BYTES=524288
JOB_QUEUE_MAX_ATTEMPTS=10
JOB_QUEUE_MAX_PRIORITY_ABS=1000
JOB_QUEUE_MAX_ID_LENGTH=128
JOB_QUEUE_MAX_TYPE_LENGTH=64
# 任务/日志查询边界(防止单次查询放大)
TASK_ACTIVE_DEFAULT_LIMIT=100
TASK_ACTIVE_MAX_LIMIT=500
TASK_LOG_DEFAULT_LIMIT=100
TASK_LOG_MAX_LIMIT=1000
TASK_QUERY_MAX_OFFSET=500000
MONITOR_LOG_DEFAULT_LIMIT=50
MONITOR_LOG_MAX_LIMIT=200
MONITOR_LOG_MAX_OFFSET=500000
# 批次与复制请求边界
TASK_BATCH_MAX_ITEMS=5000
TASK_BATCH_TEXT_MAX_LENGTH=256
TASK_BATCH_REMARK_MAX_LENGTH=2000
TASK_BATCH_LIST_DEFAULT_LIMIT=200
TASK_BATCH_LIST_MAX_LIMIT=1000
TASK_BATCH_LIST_MAX_OFFSET=500000
COPY_BATCH_TEXT_MAX_LENGTH=2048
COPY_BATCH_MAX_STATUS_COUNT=8
# 工作流请求边界
WORKFLOW_MAX_STEPS=200
WORKFLOW_MAX_DEPENDS=32
WORKFLOW_TEXT_MAX_LENGTH=128
# AI 地图分析请求边界
AI_ANALYZE_MAP_MAX_IMAGES=4
AI_ANALYZE_MAP_MAX_IMAGE_BASE64_CHARS=12582912
AI_ANALYZE_MAP_PROMPT_MAX_CHARS=8000
# 生产环境请使用白名单,不建议 *
CORS_ORIGINS=http://192.168.1.100
CORS_ALLOW_CREDENTIALS=true
CORS_STRICT_MODE=false
# 统计缓存(秒)
STATS_CACHE_TTL_SECONDS=120
# 预览缓存(可选)
RADAR_THUMBNAIL_MAX_SIZE=1600
RADAR_CACHE_WORKERS=2
# 灾害点数据源
HAZARD_POINTS_DIR=Z:\Code\Insar_management_system_v2\backend\Point
HAZARD_POINTS_FILENAME=Point.shp
```
鉴权说明:
- 系统不提供公开注册入口。
- 首次启动或重置管理员密码时,`INIT_ADMIN_PASSWORD` 为必填项(不再提供默认密码回退)。
- `scripts/init_db.py` 会检查管理员账号;若不存在则按 `INIT_ADMIN_*` 自动创建。
- 如需强制重置管理员密码:将 `INIT_ADMIN_RESET_PASSWORD=true`(仅重置当次生效,完成后建议改回 `false`)。
- 内网 HTTP 部署请保持 `AUTH_COOKIE_SECURE=false`;若启用 HTTPS,请改为 `true`
- 登录防爆破参数:`AUTH_LOGIN_MAX_FAILURES`(窗口内失败阈值)、`AUTH_LOGIN_WINDOW_SECONDS`(失败统计窗口)、`AUTH_LOGIN_LOCK_SECONDS`(触发后锁定时长)、`AUTH_LOGIN_CLEANUP_INTERVAL_SECONDS`(限流状态表后台清理间隔,秒)。
- AOI 上传限流参数:`AOI_UPLOAD_MAX_FILES`(上传文件数量上限)、`AOI_UPLOAD_MAX_SINGLE_FILE_BYTES`(单文件字节上限)、`AOI_UPLOAD_MAX_TOTAL_BYTES`(同次请求总字节上限)。超限时接口返回 `HTTP 400`
- 扫描请求边界参数:`MAX_SCAN_DIRECTORY_COUNT`(单次扫描请求目录数量上限)、`MAX_SCAN_PATH_LENGTH`(单路径字符串长度上限)。
- 高频列表查询边界参数:`LIST_QUERY_MAX_LIMIT`(单页最大返回条数)、`LIST_QUERY_MAX_OFFSET`(最大偏移)、`LIST_QUERY_MAX_WINDOW``limit+offset` 窗口上限),`LIST_QUERY_TIMEOUT_MS`PostgreSQL 列表查询超时,毫秒);`RADAR_SEARCH_OPTIONS_MAX_VALUES` / `RADAR_IMAGING_DATES_MAX_VALUES` 用于限制雷达检索选项和成像日期去重结果规模。
- 队列入队边界参数:`JOB_QUEUE_MAX_PAYLOAD_BYTES`(单任务 payload 字节上限)、`JOB_QUEUE_MAX_ATTEMPTS`(重试次数上限)、`JOB_QUEUE_MAX_PRIORITY_ABS`(优先级绝对值上限)、`JOB_QUEUE_MAX_ID_LENGTH`(关联 ID 字符上限)、`JOB_QUEUE_MAX_TYPE_LENGTH`(任务类型字符串上限)。
- 任务/日志查询边界参数:`TASK_ACTIVE_DEFAULT_LIMIT``TASK_ACTIVE_MAX_LIMIT``GET /api/tasks/active` 分页上限),`TASK_LOG_DEFAULT_LIMIT``TASK_LOG_MAX_LIMIT``TASK_QUERY_MAX_OFFSET`(任务日志分页上限),`MONITOR_LOG_DEFAULT_LIMIT``MONITOR_LOG_MAX_LIMIT``MONITOR_LOG_MAX_OFFSET``GET /api/monitor/logs` 分页与偏移上限)。
- 批次与复制请求边界参数:`TASK_BATCH_MAX_ITEMS`(单批次条目数上限)、`TASK_BATCH_TEXT_MAX_LENGTH`(批次名称/方向长度上限)、`TASK_BATCH_REMARK_MAX_LENGTH`(条目备注长度上限)、`TASK_BATCH_LIST_DEFAULT_LIMIT` / `TASK_BATCH_LIST_MAX_LIMIT` / `TASK_BATCH_LIST_MAX_OFFSET`(批次列表与明细分页上限)、`COPY_BATCH_TEXT_MAX_LENGTH`(复制接口 `batch_id`/`dest_dir` 长度上限)、`COPY_BATCH_MAX_STATUS_COUNT`(复制状态列表数量上限)。
- 工作流请求边界参数:`WORKFLOW_MAX_STEPS`(单工作流步骤上限)、`WORKFLOW_MAX_DEPENDS`(单步骤依赖数上限)、`WORKFLOW_TEXT_MAX_LENGTH`(工作流文本字段长度上限)。
- AI 地图分析请求边界参数:`AI_ANALYZE_MAP_MAX_IMAGES`(单次请求图片数上限)、`AI_ANALYZE_MAP_MAX_IMAGE_BASE64_CHARS`(单图 Base64 长度上限)、`AI_ANALYZE_MAP_PROMPT_MAX_CHARS`prompt 长度上限)。
- 授权上传默认采用“先校验后替换”的原子更新流程;无效授权不会覆盖当前在用授权文件。
- `MAX_LICENSE_UPLOAD_BYTES` 用于限制授权上传文件大小(默认 1MB)。
- `CORS_ORIGINS` 建议配置为明确白名单;生产环境不建议使用 `*`
-`CORS_STRICT_MODE=true` 时,若 `CORS_ORIGINS` 包含 `*``CORS_ALLOW_CREDENTIALS=true`,服务将拒绝启动。
- 严禁将包含真实 `DATABASE_URL``LICENSE_SECRET``.env` 提交到代码仓库或共享目录。
- 管理员可通过 `GET /api/auth/audit-logs?limit=200` 查看最近审计日志(仅 admin 可访问)。
- 许可文件上传与刷新接口(`POST /api/license/upload``POST /api/license/refresh`)仅允许管理员会话访问。
- 前端入口:左侧「运行维护」分组下新增「用户管理」「审计日志」两个管理员面板。
源影像缓存说明:
- 系统在扫描雷达源数据时,会尝试在每个场景目录中查找预览图(jpg/jpeg/png/webp/bmp/tif/tiff)并生成 WebP 缓存。
- 雷达缓存目录:`backend/image_cache/radar_geo/`(主)与 `backend/image_cache/radar_raw/`(回退)。
- D-InSAR 缓存目录:`backend/image_cache/dinsar/`(统一使用 `ID_{id}_{name}.webp`)。
- 前端「数据列表」支持源影像单条显示/隐藏与“一键显示/一键隐藏”。
- 长期稳定方案(后端预纠正缓存,B 方案)设计见:`docs/RADAR_PREVIEW_SCHEME_B.md`
---
## 11. 启动方式
### 11.1 一键启动(推荐)
双击:
```
start_system.bat
```
或命令行:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\start_app.ps1
```
说明:
- 启动链路保持不变:`start_system.bat` -> `scripts/start_app.ps1` -> `check_db_connection.py` -> `init_db.py`
- `scripts/start_app.ps1``PYTHON_PATH` 支持“绝对路径”或“命令名”(例如 `python`);脚本会先解析为可执行文件再调用。
- `init_db.py` 会在“建库/校验修复”后执行鉴权初始化(自动补齐管理员账号)。
- 扫描调度默认 Manual-only,不会后台定时自动触发;需通过前端或 `/api/monitor/run-now` 手动触发扫描。
- 默认不执行破坏性重建;若确需重建,请显式设置 `DB_SCHEMA_RESET_ON_MISMATCH=true`
### 11.2 仅启动后端(无 Nginx
```powershell
D:\anaconda3\Scripts\conda.exe run -n InSAR python run_backend.py
```
说明:后端默认绑定 `127.0.0.1`,仅本机访问。
### 11.3 后台队列 Worker(必需)
系统后台任务已改为“入队执行”,必须启动 Worker 才会真正执行扫描、AI、解包、复制等任务。
启动方式:
```powershell
D:\anaconda3\Scripts\conda.exe run -n InSAR python run_worker.py
```
说明:
- `start_system.bat` 已包含 Worker 启动。
- 若只运行 `run_backend.py`,请手动启动 `run_worker.py`
- 数据分发/复制任务仅从“批次”读取,不再支持 Excel。
- `POST /api/monitor/run-now``target` 仅支持:`radar``orbit``dinsar`(留空表示全部)。
Worker 可选环境变量:
```
JOB_WORKER_POLL_INTERVAL=1.0 # 轮询间隔(秒)
JOB_WORKER_CONCURRENCY=1 # 并发执行数
JOB_WORKER_JOB_HEARTBEAT_INTERVAL=5 # 运行中作业心跳上报间隔(秒)
JOB_WORKER_STALE_RECOVER_INTERVAL=15 # 僵尸 RUNNING 作业回收检查间隔(秒)
JOB_WORKER_STALE_RUNNING_SECONDS=300 # 判定作业僵尸的超时阈值(秒)
IDL_JOB_MAX_ATTEMPTS=6 # IDL 队列任务最大重试次数
```
ENVI/SARscape 集成(envipyengine):
- 执行引擎:`envipyengine`pip 包)→ `taskengine.exe` 子进程
- 工作流在独立 Python 子进程中执行,隔离 FastAPI 主进程
- D-InSAR 工作流自动检测未导入数据,先执行 Import 再处理 D-InSAR(智能串联)
- DEM 路径为系统级配置,存储在 `.env``IDL_DINSAR_DEM_BASE_FILE`
- 运行日志目录:`backend/runtime/idl_worker/`
ENVI 关键环境变量:
```
IDL_EXECUTABLE=... # IDL 可执行路径
IDL_WORKBENCH_PATH=... # IDL Workbench 路径
IDL_WORKER_RUNTIME_DIR=... # 运行日志目录
IDL_WORKER_DEFAULT_TIMEOUT_SECONDS=14400 # 单任务执行超时(秒)
IDL_WORKER_MAX_TIMEOUT_SECONDS=43200 # 单任务允许最大超时(秒)
IDL_DINSAR_DEM_BASE_FILE=... # DEM 路径(D-InSAR 必需)
```
API 端点(管理员):
```
GET /api/idl/status — 系统状态(含 DEM 路径和可用性)
POST /api/idl/launch-workbench — 启动 IDL Workbench
POST /api/idl/inspect/import — Import 预检查
POST /api/idl/inspect/dinsar — D-InSAR 预检查(含 Import 状态检测)
POST /api/idl/jobs/import — 提交 Import 任务
POST /api/idl/jobs/dinsar — 提交 D-InSAR 任务
GET /api/idl/jobs/recent — 最近运行记录
```
提交任务请求体示例:
```json
{
"root_dir": "Z:/Test_data/Test_IDL_1",
"num_to_process": 0,
"timeout_seconds": 14400
}
```
说明:
- 提交后会创建系统任务并入队,由 `run_worker.py` 消费执行。
- D-InSAR 工作流自动检测未导入数据,先执行 Import 再处理(智能串联)。
- DEM 路径从 `.env` 读取,不需要在请求中传递。
- Worker 在执行时会周期性更新作业心跳;若进程崩溃导致作业长期停留 `RUNNING`,会自动回收。
- 运行日志保存在 `IDL_WORKER_RUNTIME_DIR/` 下。
### 11.4 前端构建(仅构建时需要)
```powershell
cd frontend
npm install
npm run build
```
说明:
- 前端日期控件已统一为 `flatpickr`(原生实例接入),无需浏览器原生 `input[type=date]`
- 若采用“本地构建后上传 `frontend/dist`”部署方式,服务器端无需额外安装前端依赖包。
### 11.5 离线切片底图切换
前端从 `frontend/public/tiles/` 读取离线切片,当前支持三套(统一 `webp`):
- `tiles/google_image/{z}/{x}/{y}.webp`
- `tiles/gaode_image/{z}/{x}/{y}.webp`
- `tiles/gaode_shp/{z}/{x}/{y}.webp`
地图右上角「底图」按钮可在三套底图间切换(默认 `gaode_shp`,便于仅下载高德矢量时直接可用)。
缩放级别已放开到 0-16;如需调整默认底图或级别,请修改 `frontend/src/App.jsx` 中的 `TILE_LAYER_DEFAULT_KEY``TILE_LAYER_OPTIONS`
行政区边界叠加图层(地图参考边界)默认读取:
- `frontend/public/geojson/全国行政区.geojson`
建议使用 UTF-8 无 BOM 编码,且文件体积较大时优先通过 `public/` 静态加载(不要直接放入 `frontend/src` 参与打包)。
地图左上角新增「区域定位」按钮(可折叠),复用行政区二级级联(省/市):
- 可只选择到省级或市级进行定位。
- 定位时会调用后端 `/api/aoi/regions/{tree_id}/geometry` 获取边界并自动缩放到该区域。
- 定位成功后,面板会显示“当前定位”行政区名称,方便与当前视角对照。
- 面板支持「清除定位高亮」,可一键移除地图上的定位边界高亮。
- 依赖 `backend/geojson/层级映射.json``backend/geojson/全国行政区.geojson` 的行政区数据。
---
## 12. 访问与验证
- **前端**`http://SERVER_HOST`
- **后端(内部)**`http://127.0.0.1:8000`
- **接口文档(内部)**`http://127.0.0.1:8000/docs`
前端语言切换:
- 顶部状态栏新增 `中文 / EN` 切换按钮。
- 切换结果会保存在浏览器本地(`localStorage`),刷新页面后保持上次语言选择。
- 站内文案翻译映射位于 `frontend/src/i18n/translations.js`,新增界面文案时需同步补充映射,避免中英文混杂。
- 第二轮已补齐高频业务模块(批次/分发、运维自检、用户管理、审计日志、IDL 自动化、统计面板)常用文案映射。
- 第三轮已支持运行日志双语展示:右侧日志栏、数据监控日志、数据分发任务日志会随语言切换进行前端翻译。
- 当前词典已覆盖常见后端运行日志模板(扫描、拷贝、解包、任务生命周期);若新增日志模板,建议同步补充词典条目。
- 收口说明:当前前端可见业务文案已基本完成双语覆盖,剩余英文主要为样式类名/技术标识(不面向客户显示)。
---
## 13. 常用脚本说明
- `start_system.bat`:一键启动入口(调用 PowerShell 启动脚本)
- `scripts/start_app.ps1`:启动后端 + Nginx,并执行数据库检查
- `run_backend.py`:仅启动后端服务
- `run_worker.py`:后台任务 Worker(队列执行)
- `scripts/check_db_connection.py`:数据库连接检查
- `scripts/init_db.py`:数据库结构检查与初始化
- `scripts/license_manager_gui.py`:授权文件生成与续期
- `scripts/get_fingerprint.py`:机器指纹获取
- `scripts/unpack_archives.py`:解包与数据整理(支持 tar.gz)
- `scripts/pack_environment.bat`:打包 Conda 环境(如使用)
- `scripts/auth_smoke_check.py`:鉴权冒烟检查(401/403/200 核心链路)
---
## 14. 常见问题
1) **Python executable not found**
检查 `.env``PYTHON_PATH` 是否正确;可使用绝对路径,或在已激活 Conda 环境后填写 `python`
如启用 Conda 原生模式,还需确认 `CONDA_EXE``CONDA_ENV_NAME` 配置正确。
2) **数据库连接失败**
确认 PostgreSQL 服务已启动、`DATABASE_URL` 正确,并运行 `scripts/check_db_connection.py` 测试。
3) **授权无效/过期**
使用授权工具续期,检查系统时间是否回退过多。
4) **前端打不开但后端正常**
确认 Nginx 已启动、`NGINX_PATH` 正确、前端已构建。
若启动时报 `no "events" section in configuration`,请检查 `nginx/nginx.conf` 是否为空或损坏,需恢复包含 `events {}``http {}` 的完整配置。
5) **后端端口被占用(Address already in use / Access denied**
`scripts/start_app.ps1` 启动前会检查 `PORT` 对应监听占用;若被占用会直接报错并终止。
请停止占用该端口的进程,或在 `.env` 中修改 `PORT` 后重试。
脚本会在启动时自动把 `nginx/nginx.conf` 中的 `proxy_pass` 同步到该 `PORT`,无需手动改 Nginx 反向代理端口。
6) **后端或 Worker 启动后立即退出**
`scripts/start_app.ps1` 会在拉起后端与 Worker 后做快速存活检查;若进程秒退,脚本会立即报错并退出。
请优先检查终端输出与后端日志,常见原因包括端口冲突、依赖缺失、环境变量配置错误。
最小可用 `nginx.conf` 模板(按需替换路径,`proxy_pass` 端口需与 `.env``PORT` 一致):
```nginx
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
root "G:/Code/Insar_management_system_v2/frontend/dist";
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://127.0.0.1:18000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /image_cache/ {
alias "G:/Code/Insar_management_system_v2/backend/image_cache/";
}
}
}
```
### 14.1 鉴权与登录排查
- **`GET /api/auth/me` 返回 `401`**:未登录状态下这是正常现象,前端应显示登录页。
- **`POST /api/auth/login` 返回 `401`**:用户名或密码错误,先核对 `.env``INIT_ADMIN_USERNAME/INIT_ADMIN_PASSWORD`;若为首次启动且 `INIT_ADMIN_PASSWORD` 为空,初始化会直接报错。
- **`POST /api/auth/login` 返回 `429`**:触发登录限流/锁定,等待 `Retry-After` 秒后重试,或调整 `AUTH_LOGIN_MAX_FAILURES / AUTH_LOGIN_WINDOW_SECONDS / AUTH_LOGIN_LOCK_SECONDS`
- **登录后接口仍持续 `401`**:检查浏览器是否携带 Cookie(请求需 `withCredentials=true`),并确认反向代理没有丢弃 `Set-Cookie` 头。
- **需要重置管理员密码**:设置 `INIT_ADMIN_RESET_PASSWORD=true`,重启一次系统完成重置后再改回 `false`
- **Cookie 在内网 HTTP 不生效**:确认 `AUTH_COOKIE_SECURE=false`;只有 HTTPS 场景才应设置为 `true`
- **需要核查谁触发了高风险写操作**:使用 `GET /api/auth/audit-logs?limit=200`(管理员会话)。
- **需要快速回归鉴权链路**:后端启动后运行 `D:\anaconda3\Scripts\conda.exe run -n InSAR python scripts/auth_smoke_check.py --base-url http://127.0.0.1:8000`
5) **任务一直处于“执行中”**
确认 `run_worker.py` 已启动(或使用 `start_system.bat` 一键启动)。
- 若期望系统自动周期扫描:当前默认是手动模式(Manual-only),请使用前端“立即扫描”或调用 `POST /api/monitor/run-now`
6) **配对结果异常或为空**
- 影像日期需为 `YYYYMMDD` 格式(系统从文件夹名解析)。
- AOI 支持 **SHP 上传****GeoJSON 传参**`aoi_geojson`)两种模式。
- AOI Shapefile 建议使用 EPSG:4326WGS84),否则需先进行投影转换。
- 若使用“行政区选择”,请准备标准 GeoJSON(见 17.7),并确保 `features[*].properties.treeID``backend/geojson/层级映射.json` 对应。
7) **灾害点导入为 0 条**
请确保 Shapefile 中存在唯一标识字段(优先 `TYBH`),并具备经纬度或点几何:
- 必填:`TYBH`(唯一编号)
- 推荐:`hazard_type` / `hazard_name` / `city` / `county` / `township`
- 坐标:点几何优先;若无几何,则读取经度/纬度字段
数据源路径:`.env``HAZARD_POINTS_DIR` + `HAZARD_POINTS_FILENAME`(默认 `backend/Point/Point.shp`)。
8) **Excel 功能找不到了**
Excel 导入/导出已移除,请使用“任务批次 + 数据分发”流程完成复制与人工状态管理。
9) **日志出现 “got Future attached to a different loop”**
该错误通常由**子线程内创建事件循环并复用 asyncpg 连接**引起,多发生在自建 `asyncio.run(...)` 的耗时任务里。
处理方式:
- 确保所有耗时任务由 Worker 执行(统一事件循环),避免在线程内自行 `asyncio.run`
- 重启后端与 Worker 以释放异常连接。
- 如仍复现,请检查是否有自定义脚本在子线程内直接调用数据库。
---
## 15. 数据库结构自动对齐(重要)
系统每次启动会进行数据库结构检查:
- 首次启动:自动创建表结构。
- 后续启动:校验表/列/类型/可空性。
- 不一致(默认):不做破坏性重建,仅补齐缺失结构并输出告警。
- 不一致(显式开启):仅当 `DB_SCHEMA_RESET_ON_MISMATCH=true` 时执行 drop/recreate 重建。
推荐在生产/内网环境保持如下默认值(保留历史数据):
```
DB_SCHEMA_RESET_ON_MISMATCH=false
```
### 15.1 SQL 函数更新说明
若修改了 `backend/migrations/002_spatial_functions.sql`(例如配对函数 `find_dinsar_pairs`),需要执行一次:
- 重新启动系统(`start_system.bat` 会自动调用 `scripts/init_db.py`
- 或手动运行 `D:\anaconda3\Scripts\conda.exe run -n InSAR python scripts/init_db.py`
### 15.2 空间函数迁移(必需)
启动时会自动执行以下迁移文件(用于空间函数、视图与日志表):
- `backend/migrations/001_st_intersection_agg.sql`
- `backend/migrations/002_spatial_functions.sql`
如需手工修改,请保证 SQL 语法正确且使用 UTF-8 编码。
---
## 16. 工作流与任务队列(新增)
后台任务已改为队列执行(DB Job Queue):
- 复制、解包、扫描、AI 训练/预测/诊断等任务都会入队。
- Worker 执行任务并更新状态,前端可查看任务进度。
- 所有耗时任务在 Worker 的事件循环中执行,避免跨事件循环导致的 asyncpg 连接异常。
工作流 API
- `POST /api/workflow/runs` 创建工作流实例
- `GET /api/workflow/runs/{run_id}` 查询运行状态与步骤
任务查询 API(新增分页参数):
- `GET /api/tasks/active?limit=100&offset=0`
- `GET /api/tasks/{task_id}`
- `GET /api/tasks/{task_id}/logs?limit=100&offset=0`
- `GET /api/monitor/logs?limit=50&offset=0`
---
## 17. 任务批次管理(替代 Excel)
为适配 IDL 线下生产流程,D-InSAR 与 PS-InSAR 任务改为“批次”形式存储在数据库:
- 前端创建批次(不再使用 Excel 导入/导出)。
- 可按批次查看明细、手动标记完成、添加备注。
- 数据分发从批次中读取任务条目并复制到目标目录。
- Excel 导入/导出接口已移除。
相关 API
- `POST /api/task-batches/dinsar`
- `GET /api/task-batches/dinsar?limit=200&offset=0`
- `GET /api/task-batches/dinsar/{batch_id}/items?limit=200&offset=0`
- `PATCH /api/task-batches/dinsar/{batch_id}/complete-all`
- `PATCH /api/task-batches/dinsar/items/{item_id}`
- `POST /api/task-batches/ps`
- `GET /api/task-batches/ps?limit=200&offset=0`
- `GET /api/task-batches/ps/{batch_id}/items?limit=200&offset=0`
- `PATCH /api/task-batches/ps/{batch_id}/complete-all`
- `PATCH /api/task-batches/ps/items/{item_id}`
数据分发 API
- `POST /api/tools/copy-ps-stack` (body: `batch_id`, `dest_dir`, `copy_statuses?`)
- `POST /api/tools/copy-dinsar-pairs` (body: `batch_id`, `dest_dir`, `copy_statuses?`)
- `GET /api/tools/copy-status/{task_id}?limit=100&offset=0`
### 17.1 前端操作流程(推荐)
1) **生成候选列表**
- D-InSAR:左侧“干涉对配对”生成 pairs。
- PS-InSAR:左侧“PS 时序栈”生成 stack。
2) **保存为批次**
- 点击“保存批次”,系统将当前列表写入数据库。
- 批次会自动生成 `batch_id`,支持自定义名称。
- 保存成功后前端会自动切换到“任务批次”并定位到新建批次。
3) **批次管理与人工标注**
- 在右侧“任务批次”面板选择 D-InSAR 或 PS。
- 进入某批次后:
- 修改每条任务状态(PENDING / IN_PROGRESS / COMPLETED / FAILED
- 接口仅接受上述四种状态值(大小写不敏感,非法值会返回 `400`
- 为每条任务添加备注(如:文件损坏、未完成原因)
- 支持“一键全部完成”
4) **数据分发(复制)**
- 进入“数据分发”面板选择批次与目标目录后启动复制。
- 可按任务状态筛选复制(默认仅复制 `COMPLETED`)。
- 复制任务由 Worker 执行,进度可在前端日志中查看。
- 若出现部分文件复制失败,任务最终会标记为 `FAILED`(不再误报成功)。
### 17.2 批次数据结构(数据库)
系统会创建以下表:
- `dinsar_task_batches` / `dinsar_task_items`
- `ps_task_batches` / `ps_task_items`
每条 item 包含:
- `status`(人工状态)
- `remark`(备注)
- 任务路径与元数据(用于复制与后续追踪)
### 17.3 数据分发复制规则
**PS-InSAR**
- 复制源优先使用 `{original_path}_envi_import`(若存在)
- 否则使用原始路径
**D-InSAR**
- 为每个任务创建子目录:
- `<dest>/<task_name>/master`
- `<dest>/<task_name>/slave`
- 若源目录内存在 `envi_import` 且非空,优先复制 `envi_import`
### 17.4 Excel 迁移说明
历史流程若依赖 Excel
- 现在请在系统中生成批次并使用“数据分发”复制。
- 复制任务仅接收 `batch_id`,不再接收 Excel 文件。
### 17.5 API 示例(简化)
创建 D-InSAR 批次:
```json
POST /api/task-batches/dinsar
{
"name": "DINSAR_20260208",
"pairs": [
{
"task_name": "T001",
"master": {"file_path": "D:/data/master1", "...": "..."},
"slave": {"file_path": "D:/data/slave1", "...": "..."},
"time_baseline_days": 12,
"spatial_baseline_meters": 1234.5
}
]
}
```
复制 D-InSAR 批次:
```json
POST /api/tools/copy-dinsar-pairs
{
"batch_id": "xxxx-xxxx-xxxx",
"dest_dir": "D:/IDL/tasks/dinsar",
"copy_statuses": ["COMPLETED"]
}
```
### 17.6 配对参数说明(新增)
`/api/find-pairs` 支持以下可选参数(表单提交):
- `require_same_imaging_mode`:是否要求主/辅影像成像模式一致(默认 `true`,空值视为不匹配)
- `require_same_polarization`:是否要求主/辅影像极化一致(默认 `true`,空值视为不匹配)
- `aoi_overlap_threshold`AOI 覆盖比例阈值,计算方式为 `Area(image ∩ AOI) / Area(AOI)`,需主/辅影像同时满足
- `aoi_geojson`:可选,标准 GeoJSON 字符串(与 `files` 二选一或都不传)
系统会在候选配对数超过 3000 时返回提示信息。若数据库配对函数不可用,仅在影像数量 ≤1500 时允许回退计算,并返回强提醒。
前端已提供“成像模式一致 / 极化一致 / AOI 覆盖率阈值”的开关与输入框,默认关闭/0(不额外限制)。
### 17.7 行政区选择(SHP/行政区二选一)
生产规划弹窗中,AOI 来源支持:
- 上传 `SHP`(兼容旧流程)
- 行政区选择(省/市二级联动)
后端新增接口:
- `GET /api/aoi/regions/children?parent_tree_id=1`
- `GET /api/aoi/regions/{tree_id}/geometry`
相关环境变量(后端 `.env`):
```
AOI_REGION_INDEX_FILE=backend/geojson/层级映射.json
AOI_REGION_GEOJSON_FILE=backend/geojson/全国行政区.geojson
```
### 17.8 行政区 GeoJSON 数据规范(需提前准备)
建议提供一个标准 `FeatureCollection` 文件(UTF-8),示例:
```json
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"treeID": "1-23-4",
"name": "示例地市",
"level": "city"
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [[[ [116.0, 39.0], [116.2, 39.0], [116.2, 39.2], [116.0, 39.2], [116.0, 39.0] ]]]
}
}
]
}
```
字段要求:
- 必填:`properties.treeID`(与 `层级映射.json` 一致)
- 可选:`properties.name``properties.level`
- `geometry` 建议使用 EPSG:4326(经纬度)
说明:
- 当前前端行政区选择为省/市二级,不提供区县单独选择入口。
- 若仅提供区县级数据,系统会在省/市选择时自动合并其下级边界。
- 若仅提供到市级数据,前端可直接按市级选择,后端会在必要时回退到最近可用上级边界(市→省)。
-`treeID` 不匹配或缺失,行政区选择将无法返回 AOI 边界。
---
## 18. 运维自检(新增)
系统提供运维自检接口与前端面板,用于快速判断关键服务状态。
后端接口:
```
GET /api/health
```
返回约束(安全脱敏):
- 未登录或只读会话:返回最小健康摘要(`ok/timestamp` + 各子系统布尔状态与基础计数)。
- 管理员会话:返回完整诊断信息(包含错误详情、Worker 列表、外部服务状态细节)。
检查内容:
- 数据库连接 / PostGIS 扩展 / 关键表结构
- 关键表覆盖包含:任务与队列(`system_tasks/task_logs/system_jobs/scan_states`)、工作流(`workflow_defs/workflow_runs/workflow_steps/workflow_artifacts`)、鉴权(`auth_users/auth_sessions/auth_audit_logs/auth_rate_limits`)等核心表
- Worker 心跳
- IDL/ENVI 状态
- Ollama 连通性
- Nginx 连通性
- 一致性异常汇总(来自 `GET /api/statistics`):
- D-InSAR 缓存:数据库标记与实际缓存文件是否一致
- 源影像预览缓存:`READY` 状态与 `radar_geo/radar_raw` 文件是否一致
- XML 读取:是否检测到 XML 以及关键字段是否成功入库
相关环境变量:
```
JOB_WORKER_HEARTBEAT_INTERVAL=5 # Worker 心跳上报间隔(秒)
JOB_WORKER_HEALTH_TIMEOUT=60 # 运维自检判定 Worker 离线的阈值(秒)
```
前端入口:
- 左侧「系统工具」->「运维自检」
- 顶部状态栏可一键刷新自检状态
- 运维自检面板新增「一致性检测」卡片,显示异常总数、严重/一般异常,并列出具体异常项
---
## 19. 一致性统计接口(新增)
用于检查“数据库记录、缓存文件、XML读取结果”是否一致。
后端接口:
```
GET /api/statistics
```
新增返回字段(关键):
- `dinsar_cache_consistency`
- `db_cached_but_file_missing_count`:数据库标记已缓存,但缓存文件不存在
- `db_uncached_but_file_exists_count`:数据库标记未缓存,但缓存文件已存在
- `manifest_missing_file_count``cache_manifest.json` 记录的缓存文件缺失
- `source_preview_consistency`
- `preview_missing_count`:源影像预览缓存缺失(`radar_geo``radar_raw` 均不存在)
- `db_ready_but_cache_missing_count`:数据库 `READY`,但预览缓存实际缺失
- `source_xml_consistency`
- `xml_missing_count`:未检测到 XML
- `xml_detected_but_unparsed_count`:检测到 XML 但关键字段未成功入库
前端展示位置:
- 「数据统计仪表盘」:新增一致性图表与异常高亮
- 「运维自检」:新增一致性异常汇总卡片(总数 / 严重 / 一般)
建议运维动作:
- 出现 `db_cached_but_file_missing_count``db_ready_but_cache_missing_count`:执行一次重扫重建缓存
- 出现 `xml_detected_but_unparsed_count`:检查对应场景 XML 格式与解析字段
- 出现 `xml_missing_count`:检查场景目录是否包含 XML 元数据文件
---
*© 2026 InSAR Management System - 致力于更高效、更智能的雷达遥感监测*