from pydantic import BaseModel, Field class TaskCreateRequest(BaseModel): title: str category: str = "" category_id: str | None = None sub_category: str = "" description: str = "" tags: str = "" mode: str = "grab" # grab/bid/assign/recommend budget_min: int = 0 budget_max: int = 0 deadline: str = "" delivery_days: int = 0 headcount: int = 0 exclusive: bool = False task_code: str = "" display_priority: int = 0 publisher_id: str | None = None publisher_name: str = "" class TaskUpdateRequest(BaseModel): title: str | None = None category: str | None = None category_id: str | None = None sub_category: str | None = None description: str | None = None tags: str | None = None mode: str | None = None budget_min: int | None = None budget_max: int | None = None deadline: str | None = None delivery_days: int | None = None headcount: int | None = None exclusive: bool | None = None task_code: str | None = None display_priority: int | None = None publisher_id: str | None = None publisher_name: str | None = None class TaskStatusRequest(BaseModel): status: str # review/published/completed/cancelled/claimed/doing class TaskAssignRequest(BaseModel): taker_user_id: str class TaskRecommendRequest(BaseModel): candidates: list[str] = [] class TaskSelectRecommendRequest(BaseModel): taker_user_id: str class TaskCategoryItem(BaseModel): id: str name: str sort: int = 0 modes: str = "" status: str = "active" class ProviderCreateRequest(BaseModel): name: str category: str = "" level: str = "certified" status: str = "pending" contact: str = "" class ProviderUpdateRequest(BaseModel): level: str | None = None status: str | None = None contact: str | None = None class ContentCreateRequest(BaseModel): type: str = "news" title: str summary: str = "" body: str = "" cover: str = "" # 封面图 images: list[str] = [] # 图集 video: str = "" # 视频 URL video_cover: str = "" # 视频封面 link: str = "" # 外链 publisher_name: str = "" # 发布人昵称(空则用操作者) publisher_avatar: str = "" # 发布人头像 card_mode: str = "big" # big 大图 | small 小图(运营端设) is_public: bool = True # 是否公开 status: str = "draft" class ContentStatusRequest(BaseModel): status: str # published/offline/draft class ContentUpdateRequest(BaseModel): """内容更新(字段全可选,仅更新传入项)。""" type: str | None = None # policy/news/skill/dynamic title: str | None = None summary: str | None = None body: str | None = None cover: str | None = None images: list[str] | None = None video: str | None = None video_cover: str | None = None link: str | None = None publisher_name: str | None = None publisher_avatar: str | None = None card_mode: str | None = None is_public: bool | None = None source: str | None = None tenant_id: str | None = None status: str | None = None class ConfigUpdateRequest(BaseModel): value: str description: str = "" # ── 任务管理 ────────────────────────────────────────────────────────────── # ── 算力对接(compute-engine)───────────────────────────────────────────── # ── 培训业务四件套(课程 / 活动 / 报名 / 测评)→ 桥接 app.training ───────── class CourseCreateRequest(BaseModel): title: str category: str = "" level: str = "" subtitle: str = "" desc: str = "" price: float = 0 status: str = "draft" start_at: str = "" end_at: str = "" venue: str = "" quota: int = 0 image: str = "" host: str = "" class CourseStatusRequest(BaseModel): status: str # draft/published/ended/offline class CourseUpdateRequest(BaseModel): """课程更新(字段全可选,仅更新传入项)。""" title: str | None = None category: str | None = None level: str | None = None subtitle: str | None = None desc: str | None = None price: float | None = None status: str | None = None start_at: str | None = None end_at: str | None = None venue: str | None = None quota: int | None = None image: str | None = None host: str | None = None class ActivityCreateRequest(BaseModel): title: str type: str | None = None # free/salon mode: str | None = None # online/offline status: str | None = None # open/invite/pending/done/ended subtitle: str | None = None desc: str | None = None location: str | None = None host: str | None = None image: str | None = None link: str | None = None start_at: str | None = None duration_min: int | None = None capacity: int | None = None class ActivityStatusRequest(BaseModel): status: str # open/invite/pending/done/ended class ActivityUpdateRequest(BaseModel): """活动更新(字段全可选,仅更新传入项)。""" title: str | None = None type: str | None = None mode: str | None = None status: str | None = None subtitle: str | None = None desc: str | None = None location: str | None = None host: str | None = None image: str | None = None link: str | None = None start_at: str | None = None duration_min: int | None = None capacity: int | None = None class BookingUpdateRequest(BaseModel): status: str | None = None audit_status: str | None = None note: str | None = None class TestCreateRequest(BaseModel): title: str category: str = "" pass_score: int = 0 question_count: int = 30 class TestStatusRequest(BaseModel): status: str # enabled/disabled class ComputePingResponse(BaseModel): ok: bool version: str | None = None quota_per_unit: float | None = None # 引擎 1 元 = 多少配额(500000 = $1),来自 /api/status detail: str | None = None class ComputeBalanceRequest(BaseModel): """充值/调整引擎用户余额。``value`` 为配额单位(见 quota_per_unit)。""" engine_user_id: int value: int = Field(ge=0, description="调整量(配额单位),add/subtract 用") mode: str = "add" # add | subtract | override reason: str = "" class ComputeProvisionRequest(BaseModel): user_id: str class ComputeProvisionResponse(BaseModel): engine_user_id: str | None = None engine_username: str | None = None pat: str | None = None created: bool = False detail: str | None = None