Files
Neo-ZQYY/apps/backend/app/schemas/xcx_auth.py
Neo 6f8f12314f feat: 累积功能变更 — 聊天集成、租户管理、小程序更新、ETL 增强、迁移脚本
包含多个会话的累积代码变更:
- backend: AI 聊天服务、触发器调度、认证增强、WebSocket、调度器最小间隔
- admin-web: ETL 状态页、任务管理、调度配置、登录优化
- miniprogram: 看板页面、聊天集成、UI 组件、导航更新
- etl: DWS 新任务(finance_area_daily/board_cache)、连接器增强
- tenant-admin: 项目初始化
- db: 19 个迁移脚本(etl_feiqiu 11 + zqyy_app 8)
- packages/shared: 枚举和工具函数更新
- tools: 数据库工具、报表生成、健康检查
- docs: PRD/架构/部署/合约文档更新

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 00:03:48 +08:00

255 lines
9.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AI_CHANGELOG
# | 日期 | Prompt | 变更 |
# |------|--------|------|
# | 2026-03-23 | 角色路由+页面权限守卫 | WxLoginResponse 和 UserStatusResponse 增加 role 字段 |
"""
小程序认证相关 Pydantic 模型。
覆盖:微信登录、用户申请、审核、人员匹配、店铺切换等场景。
"""
from __future__ import annotations
from pydantic import Field
from app.schemas.base import CamelModel
# ── 微信登录 ──────────────────────────────────────────────
class WxLoginRequest(CamelModel):
"""微信登录请求。"""
code: str = Field(..., min_length=1, description="微信临时登录凭证")
class WxLoginResponse(CamelModel):
"""微信登录响应。"""
access_token: str
refresh_token: str
token_type: str = "bearer"
user_status: str # pending / approved / rejected / disabled
user_id: int
# CHANGE 2026-03-23 | 角色路由:登录时返回角色 code
role: str | None = None
class DevLoginRequest(CamelModel):
"""开发模式 mock 登录请求(仅 WX_DEV_MODE=true 时可用)。"""
openid: str = Field(..., min_length=1, description="模拟的微信 openid")
status: str | None = Field(None, description="模拟的用户状态;为空时保留已有用户的当前状态,新用户默认 new")
# ── 开发调试端点(仅 WX_DEV_MODE=true ─────────────────
class DevSwitchRoleRequest(CamelModel):
"""切换角色请求。替换当前用户在当前门店下的所有角色为指定角色。"""
role_code: str = Field(..., description="目标角色 codecoach/staff/head_coach/manager")
class DevSwitchStatusRequest(CamelModel):
"""切换用户状态请求。"""
status: str = Field(..., description="目标状态new/pending/approved/rejected/disabled")
class DevSwitchBindingRequest(CamelModel):
"""切换人员绑定请求。"""
binding_type: str = Field(..., description="绑定类型assistant/staff/manager")
assistant_id: int | None = Field(None, description="助教 IDbinding_type=assistant 时必填)")
staff_id: int | None = Field(None, description="员工 IDbinding_type=staff/manager 时必填)")
class DevContextResponse(CamelModel):
"""开发调试上下文信息。"""
user_id: int
openid: str | None = None
status: str
nickname: str | None = None
site_id: int | None = None
site_name: str | None = None
roles: list[str] = []
permissions: list[str] = []
binding: dict | None = None
all_sites: list[dict] = []
# ── 用户申请 ──────────────────────────────────────────────
class ApplicationRequest(CamelModel):
"""用户申请提交请求。"""
# CHANGE 2026-03-23 | 球房ID 改为 6 位字母/数字,大小写不敏感
site_code: str = Field(..., pattern=r"^[A-Za-z0-9]{6}$", description="球房ID6位字母/数字)")
applied_role_text: str = Field(..., min_length=1, max_length=100, description="申请身份")
phone: str = Field(..., pattern=r"^\d{11}$", description="手机号")
employee_number: str | None = Field(None, max_length=50, description="员工编号")
nickname: str | None = Field(None, max_length=50, description="昵称")
class ApplicationResponse(CamelModel):
"""申请记录响应。"""
id: int
site_code: str
applied_role_text: str
status: str
review_note: str | None = None
created_at: str
reviewed_at: str | None = None
class LatestApplicationDetail(CamelModel):
"""最新申请详情(含 phone/employee_number用于前端展示和预填"""
id: int
site_code: str
applied_role_text: str
phone: str
employee_number: str | None = None
status: str
review_note: str | None = None
created_at: str
reviewed_at: str | None = None
class CancelApplicationResponse(CamelModel):
"""取消申请响应(返回被取消申请的信息,用于预填重新申请表单)。"""
id: int
site_code: str
applied_role_text: str
phone: str
employee_number: str | None = None
status: str
created_at: str
# ── 用户状态 ──────────────────────────────────────────────
class UserStatusResponse(CamelModel):
"""用户状态查询响应。"""
user_id: int
status: str
nickname: str | None = None
# CHANGE 2026-03-24 | 头像:从 auth.users.avatar_url 读取
avatar_url: str | None = None
# CHANGE 2026-03-23 | 角色路由:返回用户在当前门店下的角色 code
role: str | None = None
# CHANGE 2026-03-27 | 权限改造 W2返回权限码列表前端据此动态控制页面/tab 可见性
permissions: list[str] = []
# CHANGE 2026-03-23 | banner 数据修复:补充门店名和助教等级
store_name: str | None = None
coach_level: str | None = None
applications: list[ApplicationResponse] = []
# CHANGE 2026-03-23 | 审核流程增强:最新申请详情(含 phone/employee_number
latest_application: LatestApplicationDetail | None = None
# ── 店铺 ──────────────────────────────────────────────────
class SiteInfo(CamelModel):
"""店铺信息。"""
site_id: int
site_name: str
roles: list[dict] = []
class SwitchSiteRequest(CamelModel):
"""切换店铺请求。"""
site_id: int
# ── 刷新令牌 ──────────────────────────────────────────────
class RefreshTokenRequest(CamelModel):
"""刷新令牌请求。"""
refresh_token: str = Field(..., min_length=1, description="刷新令牌")
# ── 人员匹配 ──────────────────────────────────────────────
class MatchCandidate(CamelModel):
"""匹配候选人。"""
source_type: str # assistant / staff
id: int
name: str
mobile: str | None = None
job_num: str | None = None
# ── 管理端审核 ────────────────────────────────────────────
class ApproveRequest(CamelModel):
"""批准申请请求。"""
role_id: int
binding: dict | None = None # {"assistant_id": ..., "staff_id": ..., "binding_type": ...}
review_note: str | None = None
class RejectRequest(CamelModel):
"""拒绝申请请求。"""
review_note: str = Field(..., min_length=1, description="拒绝原因")
# ── 开发调试端点(仅 WX_DEV_MODE=true ─────────────────
class DevSwitchRoleRequest(CamelModel):
"""切换角色请求。替换当前用户在当前门店下的所有角色为指定角色。"""
role_code: str = Field(..., description="目标角色 codecoach/staff/site_admin/tenant_admin")
class DevSwitchStatusRequest(CamelModel):
"""切换用户状态请求。"""
status: str = Field(..., description="目标状态new/pending/approved/rejected/disabled")
class DevSwitchBindingRequest(CamelModel):
"""切换人员绑定请求。"""
binding_type: str = Field(..., description="绑定类型assistant/staff/manager")
assistant_id: int | None = Field(None, description="助教 IDbinding_type=assistant 时必填)")
staff_id: int | None = Field(None, description="员工 IDbinding_type=staff/manager 时必填)")
class DevContextResponse(CamelModel):
"""开发调试上下文信息。"""
user_id: int
openid: str | None = None
status: str
nickname: str | None = None
site_id: int | None = None
site_name: str | None = None
roles: list[str] = []
permissions: list[str] = []
binding: dict | None = None
all_sites: list[dict] = []
# ── 开发调试端点(仅 WX_DEV_MODE=true ─────────────────
class DevSwitchRoleRequest(CamelModel):
"""切换角色请求。替换当前用户在当前门店下的所有角色为指定角色。"""
role_code: str = Field(..., description="目标角色 codecoach/staff/site_admin/tenant_admin")
class DevSwitchStatusRequest(CamelModel):
"""切换用户状态请求。"""
status: str = Field(..., description="目标状态new/pending/approved/rejected/disabled")
class DevSwitchBindingRequest(CamelModel):
"""切换人员绑定请求。"""
binding_type: str = Field(..., description="绑定类型assistant/staff/manager")
assistant_id: int | None = Field(None, description="助教 IDbinding_type=assistant 时必填)")
staff_id: int | None = Field(None, description="员工 IDbinding_type=staff/manager 时必填)")
class DevContextResponse(CamelModel):
"""开发调试上下文信息。"""
user_id: int
openid: str | None = None
status: str
nickname: str | None = None
site_id: int | None = None
site_name: str | None = None
roles: list[str] = []
permissions: list[str] = []
binding: dict | None = None
all_sites: list[dict] = []