SIT/models/field.py

195 lines
6.0 KiB
Python
Raw Permalink Normal View History

2026-01-29 09:08:31 +00:00
"""
字段业务模型
定义字段的数据结构和业务逻辑
"""
from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional, List
from config import FieldType
@dataclass
class Field:
"""
字段模型类
Attributes:
id: 字段ID
full_name: 完整名称 gis.map.location
domain: 域名 gis
sub_domains: 子域列表 ['map']
name: 字段名 location
type: 字段类型
range_min: 最小值
range_max: 最大值
default_value: 默认值
unit: 单位
description: 描述信息
created_time: 创建时间
updated_time: 更新时间
"""
full_name: str
domain: str
name: str
type: FieldType
id: Optional[int] = None
sub_domains: Optional[List[str]] = field(default_factory=list)
range_min: Optional[str] = None
range_max: Optional[str] = None
default_value: Optional[str] = None
unit: Optional[str] = None
description: Optional[str] = None
created_time: Optional[datetime] = None
updated_time: Optional[datetime] = None
def __post_init__(self):
"""初始化后处理"""
# 确保type是FieldType枚举
if isinstance(self.type, str):
self.type = FieldType(self.type)
# 从full_name解析domain、sub_domains和name
if self.full_name and not self.domain:
self._parse_full_name()
def _parse_full_name(self):
"""从完整名称解析域、子域和字段名"""
parts = self.full_name.split('.')
if len(parts) >= 2:
self.domain = parts[0]
self.name = parts[-1]
if len(parts) > 2:
self.sub_domains = parts[1:-1]
elif len(parts) == 1:
self.domain = "default"
self.name = parts[0]
@staticmethod
def build_full_name(domain: str, name: str, sub_domains: Optional[List[str]] = None) -> str:
"""
构建完整字段名
Args:
domain: 域名
name: 字段名
sub_domains: 子域列表
Returns:
完整字段名
"""
parts = [domain]
if sub_domains:
parts.extend(sub_domains)
parts.append(name)
return '.'.join(parts)
def get_sub_domains_str(self) -> str:
"""获取子域的字符串表示(用于数据库存储)"""
if self.sub_domains:
return '.'.join(self.sub_domains)
return ''
@staticmethod
def parse_sub_domains(sub_domains_str: str) -> List[str]:
"""解析子域字符串"""
if sub_domains_str:
return sub_domains_str.split('.')
return []
def validate(self) -> tuple[bool, str]:
"""
验证字段数据的有效性
Returns:
(是否有效, 错误信息)
"""
if not self.full_name:
return False, "字段完整名称不能为空"
if not self.domain:
return False, "字段域不能为空"
if not self.name:
return False, "字段名不能为空"
if not self.type:
return False, "字段类型不能为空"
# 验证范围值
if self.range_min and self.range_max:
try:
if self.type in [FieldType.INT, FieldType.FLOAT, FieldType.DOUBLE]:
min_val = float(self.range_min)
max_val = float(self.range_max)
if min_val > max_val:
return False, "最小值不能大于最大值"
except ValueError:
return False, "范围值格式不正确"
return True, ""
def to_dict(self) -> dict:
"""转换为字典"""
return {
'id': self.id,
'full_name': self.full_name,
'domain': self.domain,
'sub_domains': self.get_sub_domains_str(),
'name': self.name,
'type': self.type.value if isinstance(self.type, FieldType) else self.type,
'range_min': self.range_min,
'range_max': self.range_max,
'default_value': self.default_value,
'unit': self.unit,
'description': self.description,
'created_time': self.created_time.isoformat() if self.created_time else None,
'updated_time': self.updated_time.isoformat() if self.updated_time else None,
}
@classmethod
def from_dict(cls, data: dict) -> 'Field':
"""从字典创建对象"""
# 解析子域
sub_domains_str = data.get('sub_domains', '')
sub_domains = cls.parse_sub_domains(sub_domains_str) if sub_domains_str else []
# 解析时间
created_time = None
if data.get('created_time'):
if isinstance(data['created_time'], str):
created_time = datetime.fromisoformat(data['created_time'])
else:
created_time = data['created_time']
updated_time = None
if data.get('updated_time'):
if isinstance(data['updated_time'], str):
updated_time = datetime.fromisoformat(data['updated_time'])
else:
updated_time = data['updated_time']
return cls(
id=data.get('id'),
full_name=data['full_name'],
domain=data['domain'],
sub_domains=sub_domains,
name=data['name'],
type=data['type'],
range_min=data.get('range_min'),
range_max=data.get('range_max'),
default_value=data.get('default_value'),
unit=data.get('unit'),
description=data.get('description'),
created_time=created_time,
updated_time=updated_time,
)
def __str__(self) -> str:
"""字符串表示"""
return f"Field(id={self.id}, full_name={self.full_name}, type={self.type.value})"
def __repr__(self) -> str:
"""详细字符串表示"""
return self.__str__()