"""API 层的请求/响应数据模型(Pydantic)。 该文件集中定义后端 HTTP 接口的入参与返回结构,便于: - 校验请求字段(长度、范围等) - 生成 OpenAPI 文档 - 在路由层与前端之间形成稳定契约 """ from __future__ import annotations from datetime import datetime from typing import Any from pydantic import BaseModel, Field class HealthResponse(BaseModel): """健康检查返回。""" status: str = "ok" class SimulationStartRequest(BaseModel): """启动仿真的请求体。""" scenario: str | None = None weather: str | None = None time_period: str | None = None max_speed_kmh: int | None = Field(default=None, ge=0, le=300) duration_minutes: int | None = Field(default=None, ge=1, le=360) driver: str | None = None extra: dict[str, Any] = Field(default_factory=dict) class SimulationStartResponse(BaseModel): simulation_id: str class SimulationStopResponse(BaseModel): simulation_id: str status: str class TokenResponse(BaseModel): """登录成功后返回的 token 信息。""" access_token: str token_type: str = "bearer" expires_in: int class LoginRequest(BaseModel): """用户名密码登录请求。""" username: str = Field(min_length=1, max_length=64) password: str = Field(min_length=1, max_length=128) class RoleCreateRequest(BaseModel): """创建角色请求。""" role_id: str | None = Field(default=None, max_length=64) role_name: str = Field(min_length=1, max_length=64) role_desc: str | None = Field(default=None, max_length=255) is_active: bool = True extra: dict[str, Any] | None = None class RoleUpdateRequest(BaseModel): role_name: str | None = Field(default=None, max_length=64) role_desc: str | None = Field(default=None, max_length=255) is_active: bool | None = None extra: dict[str, Any] | None = None class RoleResponse(BaseModel): role_id: str role_name: str role_desc: str | None = None is_active: bool created_at: datetime | None = None updated_at: datetime | None = None extra: dict[str, Any] | None = None class PermissionCreateRequest(BaseModel): """创建权限点请求(perm_code 支持自定义命名规则)。""" perm_code: str = Field(min_length=1, max_length=128) perm_name: str = Field(min_length=1, max_length=128) perm_group: str | None = Field(default=None, max_length=64) perm_desc: str | None = Field(default=None, max_length=255) class PermissionResponse(BaseModel): perm_code: str perm_name: str perm_group: str | None = None perm_desc: str | None = None created_at: datetime | None = None class RolePermissionsUpdateRequest(BaseModel): perm_codes: list[str] = Field(default_factory=list) class RolePermissionsResponse(BaseModel): role_id: str perm_codes: list[str] class UserCreateRequest(BaseModel): """创建用户请求(包含明文密码,服务端将保存为哈希)。""" user_id: str | None = Field(default=None, max_length=64) username: str = Field(min_length=1, max_length=64) display_name: str | None = Field(default=None, max_length=64) password: str = Field(min_length=1, max_length=128) role_id: str = Field(min_length=1, max_length=64) is_active: bool = True extra: dict[str, Any] | None = None class UserUpdateRequest(BaseModel): display_name: str | None = Field(default=None, max_length=64) role_id: str | None = Field(default=None, max_length=64) is_active: bool | None = None extra: dict[str, Any] | None = None class UserPasswordUpdateRequest(BaseModel): new_password: str = Field(min_length=1, max_length=128) class UserResponse(BaseModel): user_id: str username: str display_name: str | None = None role_id: str role_name: str | None = None is_active: bool last_login_at: datetime | None = None created_at: datetime | None = None updated_at: datetime | None = None extra: dict[str, Any] | None = None class MeResponse(BaseModel): """当前登录用户信息返回。""" user: UserResponse class LoginResponse(BaseModel): token: TokenResponse user: UserResponse class BootstrapRequest(BaseModel): """系统首次初始化请求(仅允许在系统尚无任何用户时调用)。""" username: str = Field(min_length=1, max_length=64) password: str = Field(min_length=1, max_length=128) display_name: str | None = Field(default=None, max_length=64) class BootstrapResponse(BaseModel): token: TokenResponse user: UserResponse class UnityInitConfigRequest(BaseModel): payload: dict[str, Any] class UnityInitConfigResponse(BaseModel): simulation_id: str class UnityCommandRequest(BaseModel): payload: dict[str, Any] class UnityCommandResponse(BaseModel): ok: bool = True