You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
5.0 KiB
Python

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import re
from dataclasses import dataclass
from typing import Any
from fastapi import Query
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
from app.common.enums import QueueEnum
from app.core.base_params import BaseQueryParam, TenantByQueryParam, UserByQueryParam
from app.core.base_schema import BaseSchema, TenantBySchema, UserBySchema
from app.core.validator import DateTimeStr
class WorkflowCreateSchema(BaseModel):
"""创建工作流"""
name: str = Field(..., max_length=128, description="流程名称")
code: str = Field(..., max_length=64, description="流程编码")
description: str | None = Field(default=None, description="描述")
nodes: list | None = Field(default=None, description="Vue Flow nodes")
edges: list | None = Field(default=None, description="Vue Flow edges")
@field_validator("name")
@classmethod
def validate_name(cls, v: str) -> str:
v = v.strip()
if len(v) < 1 or len(v) > 128:
raise ValueError("流程名称长度必须在1-128个字符之间")
return v
@field_validator("code")
@classmethod
def validate_code(cls, v: str) -> str:
v = v.strip()
if len(v) < 2 or len(v) > 64:
raise ValueError("流程编码长度必须在2-64个字符之间")
if not re.match(r"^[A-Za-z][A-Za-z0-9_]*$", v):
raise ValueError("流程编码必须以字母开头,仅允许字母、数字、下划线")
return v
class WorkflowUpdateSchema(WorkflowCreateSchema):
"""更新工作流"""
workflow_status: int | None = Field(default=None, description="0:草稿 / 1:已发布 / 2:已归档")
@field_validator("workflow_status")
@classmethod
def validate_workflow_status(cls, v: int | None) -> int | None:
if v is None:
return v
allowed = {0, 1, 2}
if v not in allowed:
raise ValueError(f"流程状态必须为 {sorted(allowed)}")
return v
class WorkflowOutSchema(BaseSchema, UserBySchema, TenantBySchema):
"""工作流输出status 表示流程状态 draft/published/archived与 ModelMixin.status 区分)"""
model_config = ConfigDict(from_attributes=True)
id: int | None = Field(default=None, description="主键ID")
uuid: str | None = Field(default=None, description="UUID")
description: str | None = Field(default=None, description="描述")
created_time: DateTimeStr | None = Field(default=None, description="创建时间")
updated_time: DateTimeStr | None = Field(default=None, description="更新时间")
name: str = Field(description="流程名称")
code: str = Field(description="流程编码")
status: int = Field(description="流程状态 0:草稿 / 1:已发布 / 2:已归档")
nodes: list | None = Field(default=None, description="节点")
edges: list | None = Field(default=None, description="连线")
@model_validator(mode="before")
@classmethod
def _map_workflow_status(cls, data: Any) -> Any:
from .model import WorkflowModel
if isinstance(data, WorkflowModel):
return {
"id": data.id,
"uuid": data.uuid,
"description": data.description,
"created_time": data.created_time,
"updated_time": data.updated_time,
"created_id": data.created_id,
"updated_id": data.updated_id,
"name": data.name,
"code": data.code,
"status": data.workflow_status,
"nodes": data.nodes,
"edges": data.edges,
}
return data
@dataclass
class WorkflowQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
"""工作流查询"""
name: str | None = Query(None, description="流程名称")
code: str | None = Query(None, description="流程编码")
def __post_init__(self) -> None:
self.name = (QueueEnum.like.value, self.name) if self.name else None
self.code = (QueueEnum.like.value, self.code) if self.code else None
class WorkflowExecuteSchema(BaseModel):
"""执行工作流"""
workflow_id: int = Field(..., description="工作流ID")
variables: dict | None = Field(default=None, description="注入到各节点的 variables 上下文")
business_key: str | None = Field(default=None, description="业务键")
job_id: int | None = Field(default=None, description="关联任务ID")
class WorkflowExecuteResultSchema(BaseModel):
"""执行结果"""
workflow_id: int = Field(..., description="工作流ID")
workflow_name: str = Field(..., description="工作流名称")
status: int = Field(description="执行状态 0:失败 / 1:已完成")
start_time: str | None = Field(default=None, description="开始时间")
end_time: str | None = Field(default=None, description="结束时间")
variables: dict | None = Field(default=None, description="变量")
node_results: dict | None = Field(default=None, description="节点结果")
error: str | None = Field(default=None, description="错误信息")