Files
fquiz/api/app/tasks/elevation_tasks.py
T
chengkai3 86870f4610 feat: 高程管理重构 - 从数据集中心到文件中心
## 重构目标

将高程数据管理从"数据集中心"模式重构为"文件中心"模式,去掉 ElevationDataset 概念,
扁平化为 ElevationFileRecord,每条记录对应一个高程文件。

## 主要变更

### 数据库层
- 新增 `elevation_file_record` 表,合并原 dataset 核心字段
- 更新 `elevation_apply_job` 和 `elevation_data_import_job`,添加 `file_record_id` 字段
- 创建数据迁移脚本 `001_add_elevation_file_record.sql`
- 保留旧表用于向后兼容

### 后端 API
- 新增 `/api/v1/elevation/records` 路由组(推荐使用)
  - GET /records - 文件记录列表
  - POST /records - 上传文件并创建记录(上传即创建)
  - GET /records/{id} - 获取记录详情
  - PATCH /records/{id} - 更新记录
  - DELETE /records/{id} - 删除记录
  - POST /records/{id}/analyze - 触发分析
  - POST /records/{id}/terrain/build - 生成地形瓦片
  - GET /records/{id}/preview - 预览数据
- 保留 `/api/v1/elevation/datasets` 路由用于向后兼容
- Apply API 支持 `file_record_id` 和 `dataset_id` 双 ID

### 后端代码
- 新增 `elevation_file_record_service.py` (601 行),包含完整 CRUD 和操作逻辑
- 新增模型 `ElevationFileRecord`
- 新增 Schema:FileRecordSummary, CreateRequest, UpdateRequest 等
- 新增 Celery 任务:
  - `analyze_elevation_file_record_job`
  - `build_elevation_file_record_terrain_job`
- 新增执行函数:
  - `execute_file_record_analysis_job`
  - `execute_file_record_terrain_build_job`
- 更新模型字段,支持双 ID 关联

### 前端
- 新增简化页面 `/admin/elevation-records` (542 行)
- 从原 1760 行简化到 542 行
- 上传即创建,无需先建数据集
- 每行直接对应一个文件
- 操作更直观

### 文档
- 新增 `REFACTOR_SUMMARY.md` 完整重构说明
- 新增 `api/migrations/README.md` 迁移指南

## 用户体验改进

旧流程(4步):
1. 创建数据集(填编码+名称)
2. 导入文件到数据集
3. 分析数据集
4. 预览/地形/回填

新流程(2步):
1. 上传文件(填来源+分辨率)→ 自动创建+分析
2. 预览/地形/回填

## 向后兼容

- 保留旧表和旧 API,新旧系统可并存
- Apply Job 同时支持新旧 ID
- 提供平滑迁移路径

## 技术指标

- 代码简化:前端从 1760 行 → 542 行(-69%)
- 概念简化:去除"数据集"中间层
- API 数量:新增 8 个文件记录端点

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 09:01:16 +08:00

55 lines
2.6 KiB
Python

from __future__ import annotations
from ..core.celery_app import celery_app
from ..services.elevation_service import (
execute_apply_job,
execute_dataset_analysis_job,
execute_dataset_data_import_job,
execute_dataset_terrain_build_job,
execute_file_record_analysis_job,
execute_file_record_terrain_build_job,
)
@celery_app.task(name="app.tasks.elevation_tasks.apply_elevation_for_line_job")
def apply_elevation_for_line_job(job_id: str, actor_user_id: str | None = None) -> dict[str, str]:
execute_apply_job(job_id=job_id, actor_user_id=actor_user_id)
return {"job_id": job_id, "status": "done"}
@celery_app.task(name="app.tasks.elevation_tasks.analyze_elevation_dataset_job")
def analyze_elevation_dataset_job(dataset_id: str, actor_user_id: str | None) -> dict[str, str]:
execute_dataset_analysis_job(dataset_id=dataset_id, actor_user_id=actor_user_id)
return {"dataset_id": dataset_id, "status": "done"}
@celery_app.task(name="app.tasks.elevation_tasks.import_elevation_dataset_data_job")
def import_elevation_dataset_data_job(import_job_id: str, actor_user_id: str | None) -> dict[str, str]:
execute_dataset_data_import_job(import_job_id=import_job_id, actor_user_id=actor_user_id)
return {"import_job_id": import_job_id, "status": "done"}
@celery_app.task(name="app.tasks.elevation_tasks.build_elevation_dataset_terrain_job")
def build_elevation_dataset_terrain_job(dataset_id: str, actor_user_id: str | None) -> dict[str, str]:
execute_dataset_terrain_build_job(dataset_id=dataset_id, actor_user_id=actor_user_id)
return {"dataset_id": dataset_id, "status": "done"}
# ============================================================================
# New File Record Tasks (for file-centric API)
# ============================================================================
@celery_app.task(name="app.tasks.elevation_tasks.analyze_elevation_file_record_job")
def analyze_elevation_file_record_job(record_id: str, actor_user_id: str | None) -> dict[str, str]:
"""Analyze a single elevation file record."""
execute_file_record_analysis_job(record_id=record_id, actor_user_id=actor_user_id)
return {"record_id": record_id, "status": "done"}
@celery_app.task(name="app.tasks.elevation_tasks.build_elevation_file_record_terrain_job")
def build_elevation_file_record_terrain_job(record_id: str, actor_user_id: str | None) -> dict[str, str]:
"""Build terrain tiles for a single elevation file record."""
execute_file_record_terrain_build_job(record_id=record_id, actor_user_id=actor_user_id)
return {"record_id": record_id, "status": "done"}