refactor: 统一项目中状态字段类型为数字类型

这是一个大规模的类型对齐优化:
1.  将多处字符串类型的status字段统一改为数字类型,包括前后端接口定义、数据模型、页面组件
2.  重构编排节点相关的命名和注释,统一改为"节点类型"替代"编排节点类型"
3.  移除了过时的忘记密码相关接口和模板代码
4.  优化搜索栏组件,支持展开仅显示次要字段
5.  调整部分接口参数和路由逻辑,对齐前后端参数格式
This commit is contained in:
zhangtao
2026-06-23 00:30:40 +08:00
parent 134337b502
commit 414d5c80c3
95 changed files with 561 additions and 883 deletions
@@ -2,7 +2,7 @@
工作流编排子包(plugin.module_task.workflow):
- ``definition``: 工作流定义(画布 CRUD、发布、执行 API)
- ``node_type``: 编排节点类型(palette / 与 task_node 分离)
- ``node_type``: 节点类型(palette / 与 task_node 分离)
- ``engine``: 拓扑分层并行执行引擎
动态路由仍统一挂在 ``/task`` 下(见各子包 ``controller.py`` 的 ``prefix``)。
@@ -42,17 +42,16 @@ class WorkflowCreateSchema(BaseModel):
class WorkflowUpdateSchema(WorkflowCreateSchema):
"""更新工作流"""
workflow_status: str | None = Field(default=None, max_length=32, description="draft/published/archived")
workflow_status: int | None = Field(default=None, description="0:草稿 / 1:已发布 / 2:已归档")
@field_validator("workflow_status")
@classmethod
def validate_workflow_status(cls, v: str | None) -> str | None:
def validate_workflow_status(cls, v: int | None) -> int | None:
if v is None:
return v
allowed = {"draft", "published", "archived"}
v = v.strip()
allowed = {0, 1, 2}
if v not in allowed:
raise ValueError(f"流程状态必须为 {allowed}")
raise ValueError(f"流程状态必须为 {sorted(allowed)}")
return v
@@ -68,7 +67,7 @@ class WorkflowOutSchema(BaseSchema, UserBySchema, TenantBySchema):
updated_time: DateTimeStr | None = Field(default=None, description="更新时间")
name: str = Field(description="流程名称")
code: str = Field(description="流程编码")
status: str = Field(description="流程状态 draft/published/archived")
status: int = Field(description="流程状态 0:草稿 / 1:已发布 / 2:已归档")
nodes: list | None = Field(default=None, description="节点")
edges: list | None = Field(default=None, description="连线")
@@ -121,7 +120,7 @@ class WorkflowExecuteResultSchema(BaseModel):
workflow_id: int = Field(..., description="工作流ID")
workflow_name: str = Field(..., description="工作流名称")
status: str = Field(description="completed/failed")
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="变量")
@@ -18,6 +18,16 @@ from .schema import (
)
# 工作流状态常量(与 WorkflowModel.status 保持一致:0:草稿 1:已发布 2:已归档)
WORKFLOW_STATUS_DRAFT = 0
WORKFLOW_STATUS_PUBLISHED = 1
WORKFLOW_STATUS_ARCHIVED = 2
# 工作流执行结果状态(0:失败 1:已完成)
WORKFLOW_EXEC_STATUS_FAILED = 0
WORKFLOW_EXEC_STATUS_COMPLETED = 1
class WorkflowService:
"""工作流:画布存储 + 发布校验 + 分层并行执行"""
@@ -110,7 +120,7 @@ class WorkflowService:
description=obj.description,
nodes=obj.nodes,
edges=obj.edges,
workflow_status="published",
workflow_status=WORKFLOW_STATUS_PUBLISHED,
)
updated = await WorkflowCRUD(self.auth).update_obj_crud(id=id, data=data)
if not updated:
@@ -121,7 +131,7 @@ class WorkflowService:
obj = await WorkflowCRUD(self.auth).get_obj_by_id_crud(id=body.workflow_id)
if not obj:
raise CustomException(msg="工作流不存在")
if obj.workflow_status != "published":
if obj.workflow_status != WORKFLOW_STATUS_PUBLISHED:
raise CustomException(msg="仅已发布的工作流可执行")
nodes = obj.nodes or []
@@ -137,9 +147,9 @@ class WorkflowService:
for code in codes_set:
node_type = type_map.get(code)
if not node_type:
raise CustomException(msg=f"编排节点类型未注册(请在「工作流编排节点类型」中维护,非定时任务节点): {code}")
raise CustomException(msg=f"节点类型未注册(请在「工作流节点类型」中维护,非定时任务节点): {code}")
if not node_type.func or not str(node_type.func).strip():
raise CustomException(msg=f"编排节点类型未配置 func 代码块: {code}")
raise CustomException(msg=f"节点类型未配置 func 代码块: {code}")
templates[code] = {
"func": node_type.func,
"args": node_type.args,
@@ -165,7 +175,7 @@ class WorkflowService:
err = WorkflowExecuteResultSchema(
workflow_id=obj.id,
workflow_name=obj.name,
status="failed",
status=WORKFLOW_EXEC_STATUS_FAILED,
start_time=start,
end_time=end,
variables=variables,
@@ -178,7 +188,7 @@ class WorkflowService:
ok = WorkflowExecuteResultSchema(
workflow_id=obj.id,
workflow_name=obj.name,
status="completed",
status=WORKFLOW_EXEC_STATUS_COMPLETED,
start_time=start,
end_time=end,
variables=variables,
@@ -125,7 +125,7 @@ def run_workflow_sync(
for nid, fut in futures.items():
results[nid] = fut.result()
logger.info("工作流执行完成: nodes={}", list(results.keys()))
return {"node_results": results, "status": "completed"}
return {"node_results": results, "status": 1}
def utc_now_iso() -> str:
@@ -1 +1 @@
"""编排节点类型(palette、CRUD;与定时任务 task_node 无关)。"""
"""节点类型(palette、CRUD;与定时任务 task_node 无关)。"""
@@ -26,7 +26,7 @@ WorkflowNodeTypeRouter = APIRouter(
@WorkflowNodeTypeRouter.get(
"/options",
summary="编排节点类型选项",
summary="节点类型选项",
response_model=ResponseSchema[list[dict]],
)
async def get_workflow_node_type_options_controller(
@@ -34,12 +34,12 @@ async def get_workflow_node_type_options_controller(
) -> JSONResponse:
service = WorkflowNodeTypeService(auth)
result = await service.get_options()
return SuccessResponse(data=result, msg="获取编排节点类型选项成功")
return SuccessResponse(data=result, msg="获取节点类型选项成功")
@WorkflowNodeTypeRouter.get(
"/detail/{id}",
summary="编排节点类型详情",
summary="节点类型详情",
response_model=ResponseSchema[WorkflowNodeTypeOutSchema],
)
async def get_workflow_node_type_detail_controller(
@@ -48,12 +48,12 @@ async def get_workflow_node_type_detail_controller(
) -> JSONResponse:
service = WorkflowNodeTypeService(auth)
result_dict = await service.get_detail(id=id)
return SuccessResponse(data=result_dict, msg="获取编排节点类型详情成功")
return SuccessResponse(data=result_dict, msg="获取节点类型详情成功")
@WorkflowNodeTypeRouter.get(
"/list",
summary="编排节点类型列表",
summary="节点类型列表",
response_model=ResponseSchema[PageResultSchema[WorkflowNodeTypeOutSchema]],
)
async def get_workflow_node_type_list_controller(
@@ -71,12 +71,12 @@ async def get_workflow_node_type_list_controller(
search=search,
order_by=order_by,
)
return SuccessResponse(data=result_dict, msg="查询编排节点类型列表成功")
return SuccessResponse(data=result_dict, msg="查询节点类型列表成功")
@WorkflowNodeTypeRouter.post(
"/create",
summary="创建编排节点类型",
summary="创建节点类型",
response_model=ResponseSchema[WorkflowNodeTypeOutSchema],
)
async def create_workflow_node_type_controller(
@@ -85,12 +85,12 @@ async def create_workflow_node_type_controller(
) -> JSONResponse:
service = WorkflowNodeTypeService(auth)
result_dict = await service.create(data=data)
return SuccessResponse(data=result_dict, msg="创建编排节点类型成功")
return SuccessResponse(data=result_dict, msg="创建节点类型成功")
@WorkflowNodeTypeRouter.put(
"/update/{id}",
summary="更新编排节点类型",
summary="更新节点类型",
response_model=ResponseSchema[WorkflowNodeTypeOutSchema],
)
async def update_workflow_node_type_controller(
@@ -100,12 +100,12 @@ async def update_workflow_node_type_controller(
) -> JSONResponse:
service = WorkflowNodeTypeService(auth)
result_dict = await service.update(id=id, data=data)
return SuccessResponse(data=result_dict, msg="更新编排节点类型成功")
return SuccessResponse(data=result_dict, msg="更新节点类型成功")
@WorkflowNodeTypeRouter.delete(
"/delete",
summary="删除编排节点类型",
summary="删除节点类型",
response_model=ResponseSchema[None],
)
async def delete_workflow_node_type_controller(
@@ -114,12 +114,12 @@ async def delete_workflow_node_type_controller(
) -> JSONResponse:
service = WorkflowNodeTypeService(auth)
await service.delete(ids=ids)
return SuccessResponse(msg="删除编排节点类型成功")
return SuccessResponse(msg="删除节点类型成功")
@WorkflowNodeTypeRouter.get(
"/select",
summary="编排节点类型选择列表",
summary="节点类型选择列表",
response_model=ResponseSchema[list[dict]],
)
async def get_workflow_node_type_select_controller(
@@ -127,4 +127,4 @@ async def get_workflow_node_type_select_controller(
) -> JSONResponse:
service = WorkflowNodeTypeService(auth)
result = await service.get_select()
return SuccessResponse(data=result, msg="获取编排节点类型选择列表成功")
return SuccessResponse(data=result, msg="获取节点类型选择列表成功")
@@ -10,11 +10,11 @@ from .schema import WorkflowNodeTypeCreateSchema, WorkflowNodeTypeUpdateSchema
class WorkflowNodeTypeCRUD(CRUDBase[WorkflowNodeTypeModel, WorkflowNodeTypeCreateSchema, WorkflowNodeTypeUpdateSchema]):
"""编排节点类型 CRUD"""
"""节点类型 CRUD"""
def __init__(self, auth: AuthSchema) -> None:
"""
初始化编排节点类型 CRUD。
初始化节点类型 CRUD。
参数:
- auth (AuthSchema): 认证信息。
@@ -6,13 +6,13 @@ from app.core.base_model import ModelMixin, TenantMixin, UserMixin
class WorkflowNodeTypeModel(ModelMixin, TenantMixin, UserMixin):
"""
编排节点类型:用于 Vue Flow 左侧 palette 与执行引擎解析。
节点类型:用于 Vue Flow 左侧 palette 与执行引擎解析。
"""
__tablename__: str = "task_workflow_node_type"
__table_args__ = (
UniqueConstraint("tenant_id", "code"),
{"comment": "工作流编排节点类型(非定时任务节点)"},
{"comment": "工作流节点类型(非定时任务节点)"},
)
__loader_options__: list[str] = ["created_by", "updated_by", "deleted_by", "tenant_by"]
@@ -10,7 +10,7 @@ from app.core.base_schema import BaseSchema, TenantBySchema, UserBySchema
class WorkflowNodeTypeCreateSchema(BaseModel):
"""创建编排节点类型"""
"""创建节点类型"""
name: str = Field(..., max_length=128, description="显示名称")
code: str = Field(..., max_length=64, description="节点编码")
@@ -56,7 +56,7 @@ class WorkflowNodeTypeCreateSchema(BaseModel):
class WorkflowNodeTypeUpdateSchema(WorkflowNodeTypeCreateSchema):
"""更新编排节点类型"""
"""更新节点类型"""
class WorkflowNodeTypeOutSchema(WorkflowNodeTypeCreateSchema, BaseSchema, UserBySchema, TenantBySchema):
@@ -73,9 +73,12 @@ class WorkflowNodeTypeQueryParam(BaseQueryParam, UserByQueryParam, TenantByQuery
code: str | None = Query(None, description="编码")
category: str | None = Query(None, description="分类")
is_active: bool | None = Query(None, description="是否启用")
status: int | None = Query(None, ge=0, le=1, description="状态(0:启动 1:停用)")
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
self.category = (QueueEnum.eq.value, self.category) if self.category else None
self.is_active = (QueueEnum.eq.value, self.is_active) if self.is_active is not None else None
if isinstance(self.status, int):
self.status = (QueueEnum.eq.value, self.status)
@@ -12,7 +12,7 @@ from .schema import (
class WorkflowNodeTypeService:
"""工作流编排节点类型(与定时任务 task_node 无关)"""
"""工作流节点类型(与定时任务 task_node 无关)"""
def __init__(self, auth: AuthSchema) -> None:
self.auth = auth
@@ -38,7 +38,7 @@ class WorkflowNodeTypeService:
async def get_detail(self, id: int) -> WorkflowNodeTypeOutSchema:
obj = await WorkflowNodeTypeCRUD(self.auth).get_obj_by_id_crud(id=id)
if not obj:
raise CustomException(msg="编排节点类型不存在")
raise CustomException(msg="节点类型不存在")
return self._out(obj)
async def get_list(
@@ -85,7 +85,7 @@ class WorkflowNodeTypeService:
async def update(self, id: int, data: WorkflowNodeTypeUpdateSchema) -> WorkflowNodeTypeOutSchema:
exist = await WorkflowNodeTypeCRUD(self.auth).get_obj_by_id_crud(id=id)
if not exist:
raise CustomException(msg="编排节点类型不存在")
raise CustomException(msg="节点类型不存在")
if exist.code != data.code:
other = await WorkflowNodeTypeCRUD(self.auth).get(code=data.code)
if other: