112 lines
4.5 KiB
Python
112 lines
4.5 KiB
Python
|
"""
|
|||
|
任务输入参数模型
|
|||
|
用于存储任务输入参数的数据
|
|||
|
"""
|
|||
|
from sqlalchemy import Column, Integer, String, Text, DateTime, Boolean, ForeignKey, JSON, Enum, Index
|
|||
|
from sqlalchemy.orm import relationship, foreign
|
|||
|
from sqlalchemy.sql.expression import and_
|
|||
|
from datetime import datetime
|
|||
|
import uuid
|
|||
|
import json
|
|||
|
from data.models.base import BaseModel
|
|||
|
from config.task_config import TaskInputParamType
|
|||
|
|
|||
|
class TaskInputParam(BaseModel):
|
|||
|
"""任务输入参数模型"""
|
|||
|
__tablename__ = "task_input_params"
|
|||
|
|
|||
|
id = Column(Integer, primary_key=True, autoincrement=True, comment="主键ID")
|
|||
|
param_id = Column(String(36), nullable=False, unique=True, index=True, comment="参数唯一ID,用于外部引用")
|
|||
|
instance_id = Column(String(36), index=True, nullable=False, comment="关联的任务实例ID")
|
|||
|
task_id = Column(String(50), nullable=False, index=True, comment="任务ID,冗余存储便于查询")
|
|||
|
param_name = Column(String(50), nullable=True, comment="参数名称,变量名")
|
|||
|
label = Column(String(100), nullable=True, comment="参数标签,显示名称")
|
|||
|
param_type = Column(String(20), nullable=False, comment="参数类型")
|
|||
|
required = Column(Boolean, default=False, comment="是否必填")
|
|||
|
_default_value = Column('default_value', Text, nullable=True, comment="默认值")
|
|||
|
description = Column(Text, nullable=True, comment="参数说明")
|
|||
|
is_system = Column(Boolean, default=False, comment="是否系统参数")
|
|||
|
is_readonly = Column(Boolean, default=False, comment="是否只读参数")
|
|||
|
sort_order = Column(Integer, default=0, comment="排序顺序")
|
|||
|
|
|||
|
# 手动创建索引而不是使用外键约束
|
|||
|
__table_args__ = (
|
|||
|
Index('idx_task_input_params_instance_id', 'instance_id'),
|
|||
|
{'mysql_engine': 'InnoDB'}
|
|||
|
)
|
|||
|
|
|||
|
# 关联关系 - 使用foreign()显式标记外键
|
|||
|
instance = relationship(
|
|||
|
"TaskInstance",
|
|||
|
primaryjoin="and_(TaskInputParam.instance_id==foreign(TaskInstance.instance_id), "
|
|||
|
"TaskInstance.is_deleted==False)",
|
|||
|
foreign_keys=[instance_id],
|
|||
|
back_populates="input_params",
|
|||
|
viewonly=True
|
|||
|
)
|
|||
|
|
|||
|
def __init__(self, **kwargs):
|
|||
|
"""初始化实例,自动生成param_id"""
|
|||
|
if 'param_id' not in kwargs:
|
|||
|
kwargs['param_id'] = str(uuid.uuid4())
|
|||
|
|
|||
|
# 处理default_value参数
|
|||
|
if 'default_value' in kwargs:
|
|||
|
self.default_value = kwargs.pop('default_value')
|
|||
|
|
|||
|
super(TaskInputParam, self).__init__(**kwargs)
|
|||
|
|
|||
|
@property
|
|||
|
def default_value(self):
|
|||
|
"""获取默认值"""
|
|||
|
if self._default_value is None:
|
|||
|
return None
|
|||
|
|
|||
|
try:
|
|||
|
return json.loads(self._default_value)
|
|||
|
except (json.JSONDecodeError, TypeError):
|
|||
|
return self._default_value
|
|||
|
|
|||
|
@default_value.setter
|
|||
|
def default_value(self, value):
|
|||
|
"""设置默认值"""
|
|||
|
if value is None:
|
|||
|
self._default_value = None
|
|||
|
return
|
|||
|
|
|||
|
if isinstance(value, (str, int, float, bool)):
|
|||
|
# 基本类型直接转为JSON字符串
|
|||
|
self._default_value = json.dumps(value)
|
|||
|
elif isinstance(value, (list, dict)):
|
|||
|
# 复杂类型先验证是否可序列化,然后转为JSON字符串
|
|||
|
try:
|
|||
|
self._default_value = json.dumps(value)
|
|||
|
except:
|
|||
|
self._default_value = None
|
|||
|
else:
|
|||
|
# 其他类型尝试序列化,失败则设为None
|
|||
|
try:
|
|||
|
self._default_value = json.dumps(value)
|
|||
|
except:
|
|||
|
self._default_value = None
|
|||
|
|
|||
|
def to_dict(self):
|
|||
|
"""转换为字典"""
|
|||
|
return {
|
|||
|
"id": self.param_id, # 使用param_id作为对外ID
|
|||
|
"param_id": self.param_id,
|
|||
|
"instance_id": self.instance_id,
|
|||
|
"task_id": self.task_id,
|
|||
|
"param_name": self.param_name,
|
|||
|
"label": self.label,
|
|||
|
"param_type": self.param_type,
|
|||
|
"required": self.required,
|
|||
|
"default_value": self.default_value,
|
|||
|
"description": self.description,
|
|||
|
"is_system": self.is_system,
|
|||
|
"is_readonly": self.is_readonly,
|
|||
|
"sort_order": self.sort_order,
|
|||
|
"created_at": int(self.created_at.timestamp() * 1000) if self.created_at else None,
|
|||
|
"updated_at": int(self.updated_at.timestamp() * 1000) if self.updated_at else None,
|
|||
|
"is_deleted": self.is_deleted
|
|||
|
}
|