""" 字段映射模型 用于存储 AI 识别的字段映射结果 """ from datetime import datetime from typing import List, Optional from sqlalchemy import ForeignKey, Integer, String, Float, Boolean, DateTime, JSON, Text from sqlalchemy.orm import Mapped, mapped_column, relationship from app.models.base import BaseModel class FieldMapping(BaseModel): """ 字段映射模型 记录源字段到标准字段的映射关系 """ __tablename__ = "field_mappings" company_id: Mapped[int] = mapped_column(Integer, ForeignKey("companies.id"), nullable=False, index=True) file_id: Mapped[int] = mapped_column(Integer, ForeignKey("uploaded_files.id"), nullable=False, index=True) source_field: Mapped[str] = mapped_column(String(100), nullable=False, comment="源字段名") standard_field: Mapped[str] = mapped_column(String(100), nullable=False, comment="标准字段名") confidence: Mapped[float] = mapped_column(Float, nullable=False, default=0.0, comment="置信度 0-1") confirmed: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, comment="是否已确认") confirmed_by: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("users.id"), nullable=True) confirmed_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True) sample_values: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True, comment="样例值") reasoning: Mapped[Optional[str]] = mapped_column(Text, nullable=True, comment="AI 判断依据") is_skipped: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, comment="是否跳过") # 关系 company = relationship("Company", back_populates="field_mappings") file = relationship("UploadedFile", back_populates="field_mappings") confirmed_by_user = relationship("User", foreign_keys=[confirmed_by]) def __repr__(self) -> str: return f" standard='{self.standard_field}', confidence={self.confidence})>"