# AcidMap 项目开发规范 (PROJECT RULES) ## 0. 规则文件维护指导 (RULES MAINTENANCE GUIDE) ### 0.1 规则更新原则 **重要提示**: 当项目发生以下变化时,开发人员和AI助手必须同步更新本规则文件: #### 0.1.1 必须更新的情况 1. **新功能模块集成** - 添加新的业务功能、API端点或服务组件 2. **架构变更** - 修改目录结构、分层架构或技术栈 3. **开发规范变更** - 修改编码规范、注释风格或命名约定 4. **部署环境变更** - 更新依赖包、数据库版本或服务器配置 5. **API接口变更** - 新增、修改或删除API路由和响应格式 #### 0.1.2 更新流程 1. **识别变更影响** - 确定变更影响的规范章节 2. **更新相关章节** - 修改对应的规范内容和示例 3. **验证一致性** - 确保规范与实际代码实现一致 4. **文档同步** - 同时更新相关的集成文档和使用指南 #### 0.1.3 AI助手责任 - 在进行功能开发或架构调整时,主动识别需要更新的规范内容 - 确保新增功能的开发遵循现有规范,或合理扩展规范 - 提醒维护相关文档的同步更新 ## 1. 项目概述 ### 1.1 项目基本信息 - **项目名称**: AcidMap (地图数据处理与预测分析系统) - **技术栈**: FastAPI + PostgreSQL + PostGIS + PyTorch - **主要功能**: 栅格和矢量地理数据的处理、存储、管理和Cd预测分析 - **开发语言**: Python 3.8+ - **架构模式**: 分层架构 (API层 -> Service层 -> Model层) ### 1.2 核心业务域 - 栅格数据处理 (Raster Data Processing) - 矢量数据处理 (Vector Data Processing) - 空间数据查询和分析 - GIS数据导入导出 - Cd预测模型分析 (Cd Prediction Analysis) - 作物Cd含量预测 - 有效态Cd含量预测 - 预测结果可视化 ## 2. 项目架构 ### 2.1 目录结构规范 ``` AcidMap/ ├── app/ # 应用核心代码 │ ├── api/ # API路由层 │ │ ├── raster.py # 栅格数据接口 │ │ ├── vector.py # 矢量数据接口 │ │ └── cd_prediction.py # Cd预测模型接口 │ ├── services/ # 业务逻辑层 │ │ ├── raster_service.py │ │ ├── vector_service.py │ │ └── cd_prediction_service.py # Cd预测业务服务 │ ├── models/ # 数据模型层 │ │ ├── base.py # 基础模型 │ │ ├── orm_models.py # ORM模型 │ │ ├── raster.py # 栅格数据模型 │ │ ├── vector.py # 矢量数据模型 │ │ ├── county.py # 县域数据模型 │ │ └── farmland.py # 农田样点数据模型 │ ├── utils/ # 工具函数 │ │ ├── file_validators.py │ │ └── cd_prediction_wrapper.py # Cd预测系统包装器 │ ├── config/ # 配置管理 │ │ ├── __init__.py │ │ └── cd_prediction_config.py # Cd预测配置管理 │ ├── static/ # 静态文件 │ │ └── cd_predictions/ # Cd预测输出文件 │ │ ├── figures/ # 地图和直方图 │ │ ├── raster/ # 栅格文件 │ │ ├── reports/ # 报告文件 │ │ └── data/ # 数据文件 │ ├── logs/ # 日志文件 │ ├── scripts/ # 脚本文件 │ ├── database.py # 数据库配置 │ └── main.py # FastAPI应用入口 ├── Cd_Prediction_Integrated_System/ # Cd预测系统 │ ├── models/ # 预测模型 │ │ ├── crop_cd_model/ │ │ └── effective_cd_model/ │ ├── analysis/ # 数据分析模块 │ ├── utils/ # 工具函数 │ ├── data/ # 数据文件 │ ├── output/ # 输出文件 │ ├── main.py # 主执行脚本 │ └── config.py # 配置文件 ├── data/ # 数据文件 │ └── counties.geojson # 县域地理数据 ├── migrations/ # 数据库迁移文件 ├── scripts/ # 项目脚本 ├── ssl/ # SSL证书文件 ├── config.env # 环境配置 ├── environment.yml # Conda环境依赖 ├── soilgd.sql # 数据库备份文件 ├── db_migrate.py # 数据库迁移脚本 ├── reset_db.py # 数据库重置脚本 ├── test_cd_integration.py # Cd集成测试脚本 ├── INTEGRATION_GUIDE.md # 集成使用指南 ├── CD_INTEGRATION_SUMMARY.md # 集成总结文档 └── main.py # 应用启动入口 ``` ### 2.2 分层架构说明 1. **API层 (app/api/)**: 处理HTTP请求,参数验证,调用Service层 2. **Service层 (app/services/)**: 业务逻辑处理,数据转换,调用Model层 3. **Model层 (app/models/)**: 数据模型定义,数据库操作 4. **Utils层 (app/utils/)**: 通用工具函数,验证器等 5. **Config层 (app/config/)**: 配置管理,环境设置 ## 3. 开发规范 ### 3.1 代码规范 #### 3.1.1 注释规范 **必须使用JSDoc风格注释**: ```python def process_raster_data(file_path: str, options: dict) -> dict: """ 处理栅格数据文件 @param {str} file_path - 栅格文件路径 @param {dict} options - 处理选项配置 @returns {dict} 处理结果,包含状态和数据信息 @throws {ValueError} 当文件路径无效时抛出 @example >>> result = process_raster_data('/path/to/file.tif', {'format': 'GeoTIFF'}) >>> print(result['status']) """ pass ``` #### 3.1.2 命名规范 - **文件名**: 使用下划线分隔 (snake_case) - **类名**: 使用帕斯卡命名 (PascalCase) - **函数名**: 使用下划线分隔 (snake_case) - **变量名**: 使用下划线分隔 (snake_case) - **常量名**: 全大写下划线分隔 (UPPER_SNAKE_CASE) #### 3.1.3 导入规范 ```python # 标准库导入 import os import logging from typing import List, Dict, Optional # 第三方库导入 from fastapi import FastAPI, HTTPException from sqlalchemy import create_engine from geoalchemy2 import Geometry # 本地模块导入 from .models import Base from .services import RasterService ``` ### 3.2 API设计规范 #### 3.2.1 路由组织 - 栅格数据: `/api/raster/*` - 矢量数据: `/api/vector/*` - **Cd预测分析: `/api/cd-prediction/*`** - 使用RESTful设计原则 #### 3.2.2 HTTP状态码 - 200: 成功 - 201: 创建成功 - 400: 客户端错误 - 404: 资源未找到 - 500: 服务器错误 #### 3.2.3 响应格式 ```python { "success": true, "message": "操作成功", "data": {...}, "error": null } ``` ### 3.3 数据库规范 #### 3.3.1 数据库配置 - 数据库: PostgreSQL 12+ - 空间扩展: PostGIS 3.0+ - 连接池: SQLAlchemy连接池管理 - 环境配置: config.env文件 #### 3.3.2 模型定义 - 继承Base类 - 使用GeoAlchemy2处理空间数据 - 添加适当的索引和约束 #### 3.3.3 迁移管理 - 使用Alembic进行数据库迁移 ### 3.4 可视化规范 #### 3.4.1 分辨率设置 - **默认DPI**: 300 (标准分辨率输出) - **高分辨率DPI**: 600 (高质量输出) - **高分辨率模式**: 支持通过`high_res=True`参数启用600 DPI输出 - **图像格式**: JPG格式,支持bbox_inches='tight'自动裁切 #### 3.4.2 分辨率配置层级 1. **配置文件级别**: `config.VISUALIZATION_CONFIG["dpi"] = 300` 2. **matplotlib全局设置**: `plt.rcParams['savefig.dpi'] = 300` 3. **方法参数级别**: `high_res`参数可动态控制输出DPI #### 3.4.3 可视化方法接口 - **栅格地图**: `create_raster_map(high_res=False)` - 默认300 DPI标准分辨率输出 - **直方图**: `create_histogram(high_res=False)` - 默认300 DPI标准分辨率输出 - **图像尺寸**: 可通过`figure_size`和`figsize`参数调整 #### 3.4.4 字体配置 - 优先使用Windows系统中文字体: Microsoft YaHei, SimHei等 - 支持跨平台字体回退机制 - 自动字体缓存重建解决字体问题 - 保持迁移文件版本控制 - 提供数据库重置脚本 ## 4. 核心组件说明 ### 4.1 数据库层 (database.py) ```python # 核心配置项 - SQLALCHEMY_DATABASE_URL: 数据库连接字符串 - SessionLocal: 会话工厂 - get_db(): 依赖注入函数 - execute_sql(): 原生SQL执行 ``` ### 4.2 API路由层 - **栅格API (api/raster.py)**: 处理栅格数据的CRUD操作 - **矢量API (api/vector.py)**: 处理矢量数据的CRUD操作 - **Cd预测API (api/cd_prediction.py)**: 处理Cd预测模型的调用和结果获取 ### 4.3 业务服务层 - **RasterService**: 栅格数据业务逻辑 - **VectorService**: 矢量数据业务逻辑 - **CdPredictionService**: Cd预测分析业务逻辑 ### 4.4 数据模型层 - **ORM模型**: 数据库表映射 - RasterData: 栅格数据模型 - VectorData: 矢量数据模型 - Counties: 县域地理数据模型 - FarmlandData: 农田样点空间位置与索引数据模型 - **Pydantic模型**: API输入输出验证 ### 4.5 Cd预测系统组件 - **CdPredictionWrapper**: Cd预测系统包装器 - **CdPredictionConfig**: Cd预测配置管理 - **作物Cd预测模型**: 基于神经网络的作物Cd含量预测 - **有效态Cd预测模型**: 基于神经网络的有效态Cd含量预测 ## 5. 开发流程 ### 5.1 新功能开发流程 1. **需求分析**: 确定功能边界和技术方案 2. **数据模型设计**: 设计相关的数据库表和ORM模型 3. **Service层开发**: 实现业务逻辑 4. **API层开发**: 实现HTTP接口 5. **测试**: 单元测试和集成测试 6. **文档更新**: 更新API文档和代码注释 7. **规则文件更新**: 更新PROJECT_RULES.md中的相关规范 ### 5.2 数据库变更流程 #### 5.2.1 数据库表格添加标准流程 **第一步: 创建/修改 ORM 模型** 1. 在 `app/models/` 目录下创建或编辑模型文件 2. 定义SQLAlchemy ORM模型类,继承Base类 3. 确保在 `app/models/__init__.py` 中导入新模型 ```python # 实际案例: 农田数据模型 # app/models/farmland.py from sqlalchemy import Column, Integer, Float from geoalchemy2 import Geometry from app.database import Base # 统一的Base导入 class FarmlandData(Base): """ 农田样点空间位置与索引数据模型 @param {int} farmland_id - 区域农业用地矢量点编号(主键) @param {int} sample_id - 采样自增的ID(主键+自增) @param {float} lon - 经度 @param {float} lan - 纬度 @param {float} type - 用地类型:旱地(0)、水田(1)、水浇地(2) """ __tablename__ = 'Farmland_data' __table_args__ = {'comment': '农田样点空间位置与索引数据模型'} farmland_id = Column('Farmland_ID', Integer, primary_key=True) sample_id = Column('Sample_ID', Integer, primary_key=True, autoincrement=True) lon = Column('lon', Float, nullable=True) lan = Column('lan', Float, nullable=True) type = Column('Type', Float, nullable=True) geom = Column(Geometry('POINT', srid=4326)) ``` **第二步: 使用迁移脚本生成迁移文件** ```bash # 使用项目自带的迁移脚本 python db_migrate.py create "添加新数据表" # 或直接使用alembic命令 alembic revision --autogenerate -m "添加新数据表" ``` **第三步: 检查生成的迁移文件** 1. 查看 `migrations/versions/` 目录下新生成的迁移文件 2. 验证迁移内容是否正确 3. 必要时手动调整迁移脚本 **第四步: 执行数据库迁移** ```bash # 使用项目迁移脚本 python db_migrate.py upgrade # 或直接使用alembic命令 alembic upgrade head ``` **第五步: 验证迁移结果** ```bash # 查看当前数据库版本 python db_migrate.py current # 查看迁移历史 python db_migrate.py history ``` #### 5.2.2 使用sqlacodegen反向生成模型 (可选) 当需要从现有数据库表生成ORM模型时: ```bash # 反向生成所有表的模型 sqlacodegen postgresql://postgres:123456789Qq@localhost/soilgd > models.py # 生成特定表的模型 sqlacodegen postgresql://postgres:123456789Qq@localhost/soilgd --tables table1,table2 > specific_models.py ``` #### 5.2.3 数据库脚本命令参考 **db_migrate.py 脚本命令**: - `python db_migrate.py create "描述"` - 创建新迁移 - `python db_migrate.py upgrade` - 升级到最新版本 - `python db_migrate.py downgrade` - 降级到上一版本 - `python db_migrate.py current` - 显示当前版本 - `python db_migrate.py history` - 显示迁移历史 - `python db_migrate.py stamp head` - 标记数据库版本 #### 5.2.4 数据导入脚本开发规范 ##### 5.2.4.1 脚本开发原则 - **统一模式**: 所有导入脚本应遵循统一的结构和错误处理模式 - **参考现有脚本**: 可参考 `scripts/import_counties.py` (GeoJSON导入) 和 `scripts/import_farmland_data.py` (Excel导入) - **完整日志**: 实现详细的操作日志记录 - **事务安全**: 确保数据完整性,支持回滚机制 - **批量处理**: 大数据集使用批量插入优化性能 ##### 5.2.4.2 数据导入脚本模板结构 ```python """ 数据导入脚本模板 @description: [描述导入的数据类型和来源] """ import os import sys import logging # 添加项目根目录到Python路径 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from app.database import SessionLocal from app.models.[model_file] import [ModelClass] # 设置日志 logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) class [DataType]Importer: """ [数据类型]导入器 """ def __init__(self, file_path: str): self.file_path = file_path def read_data(self): """读取数据文件""" pass def validate_data(self, data): """验证数据格式和完整性""" pass def import_data(self, data): """将数据导入到数据库""" db = SessionLocal() try: # 批量处理逻辑 # 事务提交 db.commit() logger.info("数据导入完成") except Exception as e: db.rollback() logger.error(f"数据导入失败: {str(e)}") raise finally: db.close() def run_import(self): """执行完整的导入流程""" try: data = self.read_data() validated_data = self.validate_data(data) self.import_data(validated_data) except Exception as e: logger.error(f"导入流程失败: {str(e)}") raise def main(): file_path = "path/to/data/file" importer = [DataType]Importer(file_path) importer.run_import() if __name__ == "__main__": main() ``` ##### 5.2.4.3 GeoJSON数据导入参考 **参考脚本**: `scripts/import_counties.py` 主要特点: - 使用JSON模块读取GeoJSON文件 - 通过模型类的`from_geojson_feature`方法处理几何数据 - 完整的错误处理和日志记录 - 事务安全保证 ```python # 核心导入逻辑示例 def import_counties_from_geojson(file_path: str, db: Session): with open(file_path, 'r', encoding='utf-8') as f: geojson_data = json.load(f) for feature in geojson_data['features']: try: county = County.from_geojson_feature(feature) db.add(county) logger.info(f"成功导入: {county.name}") except Exception as e: logger.error(f"导入失败: {str(e)}") continue db.commit() ``` ##### 5.2.4.4 Excel数据导入参考 **参考脚本**: `scripts/import_farmland_data.py` 主要特点: - 使用pandas读取Excel文件和指定sheet - 支持数据类型转换和映射(如Type字段映射) - 自动生成PostGIS几何对象 - 批量插入优化(1000条/批次) - 数据验证和清洗 ```python # 核心导入逻辑示例 class FarmlandDataImporter: def __init__(self, excel_path, sheet_name='Farmland'): self.excel_path = excel_path self.sheet_name = sheet_name self.type_mapping = {'旱': 0.0, '水田': 1.0, '水浇地': 2.0} def read_excel_data(self): df = pd.read_excel(self.excel_path, sheet_name=self.sheet_name) return df def validate_data(self, df): # 数据类型转换 df['Type_Numeric'] = df['Type'].map(self.type_mapping) return df def create_geometry(self, lon, lat): return WKTElement(f'POINT({lon} {lat})', srid=4326) def import_data(self, df): # 批量导入逻辑 batch_size = 1000 for i in range(0, len(df), batch_size): batch_objects = [] # ... 创建批次对象 db.add_all(batch_objects) db.commit() ``` ##### 5.2.4.5 数据导入最佳实践 1. **文件路径检查**: 导入前验证数据文件是否存在 2. **数据预览**: 读取数据后显示前几行供确认 3. **字段映射**: 建立清晰的字段映射表(如类型编码转换) 4. **几何数据处理**: 自动生成PostGIS兼容的几何对象 5. **批量操作**: 大数据集分批处理,避免内存溢出 6. **进度跟踪**: 显示导入进度和统计信息 7. **异常处理**: 跳过无效数据行,记录详细错误信息 8. **结果验证**: 导入完成后验证数据库中的记录数量 ##### 5.2.4.6 常用数据源类型 - **GeoJSON**: 地理空间矢量数据(参考`import_counties.py`) - **Excel/CSV**: 结构化表格数据(参考`import_farmland_data.py`) - **Shapefile**: GIS矢量数据(使用geopandas读取) - **GeoTIFF**: 栅格地理数据(使用rasterio处理) #### 5.2.5 注意事项 - 备份数据库后再执行迁移 - 在开发环境先测试迁移 - 保持迁移文件的版本控制 - 迁移失败时及时回滚 - **Base类统一性**:所有模型必须使用`app.database`中的同一个Base实例 - ❌ 错误:`from .base import Base`(会创建独立的Base) - ✅ 正确:`from app.database import Base`(使用统一的Base) ### 5.3 代码提交规范 - feat: 新功能 - fix: 修复bug - docs: 文档更新 - refactor: 代码重构 - test: 测试相关 - **integrate: 系统集成** ### 5.4 Cd预测功能开发流程 1. **模型验证**: 确保Cd预测系统完整性 2. **包装器开发**: 创建系统调用包装器 3. **服务层集成**: 实现异步预测服务 4. **API接口开发**: 创建预测和下载接口 5. **文件管理**: 实现输出文件的管理和清理 6. **集成测试**: 运行完整的集成测试脚本 ## 6. 环境配置 ### 6.1 开发环境要求 - Python 3.8+ ### 数据库备份与恢复: #### 备份操作 ```bash # 自定义格式(推荐,文件小,支持选择性恢复) pg_dump -U postgres -Fc soilgd > soilgd.dump # SQL文本格式(兼容性好,可读性强) pg_dump -U postgres soilgd > soilgd.sql ``` #### 导入操作 ```bash # 导入自定义格式备份,若soilgd已存在,需要删除该数据库重新创建 createdb -U postgres soilgd pg_restore -U postgres -d soilgd soilgd.dump # 导入SQL文本格式备份 createdb -U postgres soilgd psql -U postgres -d soilgd -f soilgd.sql ``` #### 快速参考 | 导出格式 | 导出命令 | 导入命令 | |---------|---------|---------| | 自定义格式 | `pg_dump -Fc` | `pg_restore` | | SQL文本 | `pg_dump` | `psql` | #### 注意事项 - 格式必须匹配:`pg_dump -Fc` 导出 → `pg_restore` 导入 ### 6.2 环境配置文件 - `config.env`: 数据库连接配置 - `environment.yml`: Conda环境依赖 ### 6.3 启动命令 ```bash # 开发环境 uvicorn app.main:app --reload # 生产环境 uvicorn app.main:app --host 0.0.0.0 --port 8000 # Cd集成测试 python test_cd_integration.py ``` ## 7. 安全规范 ### 7.1 CORS配置 - 限制允许的源域名 - 配置适当的HTTP方法和头部 ### 7.2 数据库安全 - 使用环境变量管理敏感信息 - 实施连接池管理 - SQL注入防护 ### 7.3 文件上传安全 - 文件类型验证 - 文件大小限制 - 恶意文件检测 ### 7.4 Cd预测系统安全 - 预测任务超时控制 (5分钟) - 输出文件访问权限管理 - 敏感路径信息隐藏 - 异常信息安全过滤 ## 8. 性能优化 ### 8.1 数据库优化 - 适当的索引设计 - 查询优化 - 连接池配置 ### 8.2 API优化 - 响应压缩 - 缓存策略 - 分页处理 ### 8.3 Cd预测性能优化 - 异步任务处理 (asyncio) - CPU密集型任务线程池执行 - 预测结果文件缓存 - 自动文件清理 (最多保留10个) ## 9. 错误处理 ### 9.1 异常分类 - 业务异常: 4xx HTTP状态码 - 系统异常: 5xx HTTP状态码 - 数据库异常: 专门的错误处理 ### 9.2 日志记录 - 使用Python logging模块 - 分级别记录日志 - 敏感信息脱敏 ### 9.3 Cd预测错误处理 - 预测系统完整性检查 - 依赖包缺失检测 - 预测超时异常处理 - 文件生成失败回退机制 ## 10. 测试规范 ### 10.1 测试覆盖 - 单元测试: Service层和Utils层 - 集成测试: API端点测试 - 数据库测试: 模型和查询测试 ### 10.2 测试数据 - 使用测试数据库 - 测试数据隔离 - 数据清理策略 ### 10.3 Cd预测测试规范 - 配置模块测试 - 包装器功能测试 - API端点注册验证 - 文件系统完整性检查 ## 11. 部署规范 ### 11.1 部署环境 - 支持Docker容器化部署 - SSL证书配置 - 环境变量管理 ### 11.2 监控和维护 - 应用性能监控 - 错误日志监控 - 数据库性能监控 ### 11.3 Cd预测部署特殊要求 - 确保Cd_Prediction_Integrated_System目录完整 - 验证地理空间库安装 (fiona, pyogrio) - 配置预测输出目录权限 - 监控预测任务执行时间 ## 12. API文档规范 ### 12.1 Cd预测API端点 #### 一键接口 (生成并直接返回图片) ``` POST /api/cd-prediction/crop-cd/generate-and-get-map POST /api/cd-prediction/effective-cd/generate-and-get-map POST /api/cd-prediction/crop-cd/generate-and-get-histogram POST /api/cd-prediction/effective-cd/generate-and-get-histogram ``` #### 分步式接口 (先生成后下载) ``` POST /api/cd-prediction/crop-cd/generate-map POST /api/cd-prediction/effective-cd/generate-map GET /api/cd-prediction/crop-cd/download-map GET /api/cd-prediction/effective-cd/download-map GET /api/cd-prediction/crop-cd/download-histogram GET /api/cd-prediction/effective-cd/download-histogram ``` ### 12.2 一键接口特点 - **即时响应**: 生成完成后直接返回图片文件 - **简化操作**: 无需分两步操作,一次调用完成 - **适用场景**: 前端直接显示、浏览器预览、快速下载 - **返回格式**: 直接返回`FileResponse`图片文件 ### 12.3 分步式接口特点 - **灵活控制**: 可以先生成后选择性下载 - **状态查询**: 生成接口返回详细的统计信息 - **批量操作**: 生成一次可多次下载不同格式 - **返回格式**: JSON响应包含文件路径和统计信息 ### 12.4 响应格式规范 #### 一键接口响应 ``` Content-Type: image/jpeg Content-Disposition: attachment; filename="crop_cd_prediction_map.jpg" [图片文件二进制数据] ``` #### 分步式接口响应 ```json { "success": true, "message": "作物Cd预测地图生成成功", "data": { "map_path": "string", "histogram_path": "string", "raster_path": "string", "prediction_stats": {} }, "error": null } ``` ### 12.5 文档维护 - 使用FastAPI自动生成文档 (`/docs`) - 更新API变更日志 --- ## 总结 本规范文档旨在为AcidMap项目的开发提供统一的标准和指导。所有开发人员和AI助手在进行功能开发、代码维护和系统扩展时,都应严格遵循本规范,以确保代码质量、系统稳定性和开发效率。 **重要提醒**: 本规范文件应与项目功能同步更新。任何新功能集成、架构调整或开发流程变更都必须及时反映到相应的规范章节中。 遇到规范未覆盖的情况时,应优先考虑: 1. 代码可读性和可维护性 2. 系统安全性和稳定性 3. 性能优化和用户体验 4. 与现有架构的一致性 **最后更新**: 2025-06-14 (新增数据库导入脚本开发规范和农田数据模型)