包含多个会话的累积代码变更: - 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>
118 lines
5.1 KiB
Python
118 lines
5.1 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
租户管理后台 — 用户审核 + 用户管理 Pydantic Schema。
|
||
|
||
覆盖:申请列表、关联建议、审核通过/拒绝、用户列表、编辑、绑定、角色列表、人员候选。
|
||
|
||
需求: 3.2, 4.1
|
||
|
||
AI_CHANGELOG
|
||
- 2026-03-23 17:00:00 | Prompt: P20260323-164500(审核弹窗改造)| Direct cause:新增 roles + site-staff 端点需要响应 Schema | Summary:新增 RoleItem(角色列表项)+ StaffCandidate(人员候选项,source 区分 assistant/staff)| Verify:后端 /roles 和 /site-staff 返回正确 JSON 结构
|
||
- 2026-03-24 | Prompt: 用户管理绑定功能改造 | Direct cause:UserEditRequest 需要同时携带角色+绑定字段 | Summary:UserEditRequest 扩展 assistant_id/staff_id 字段,支持角色+绑定合并提交 | Verify:PATCH /users/{id} 接受 assistantId/staffId 参数
|
||
- 2026-03-24 | Prompt: 审核弹窗头像昵称+排版优化 | Direct cause:ApplicationListItem 缺少 avatar_url | Summary:新增 avatar_url 字段 | Verify:GET /applications 返回 avatarUrl
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from pydantic import Field
|
||
|
||
from app.schemas.base import CamelModel
|
||
|
||
|
||
# ── 用户申请审核 ──────────────────────────────────────────
|
||
|
||
|
||
class ApplicationListItem(CamelModel):
|
||
"""申请列表项。"""
|
||
id: int
|
||
user_id: int
|
||
nickname: str | None = None
|
||
avatar_url: str | None = None
|
||
phone: str | None = None
|
||
site_code: str | None = None
|
||
applied_role_text: str | None = None
|
||
employee_number: str | None = None
|
||
created_at: str | None = None
|
||
status: str # pending / approved / rejected
|
||
|
||
|
||
class MatchSuggestion(CamelModel):
|
||
"""关联匹配建议。"""
|
||
assistant_id: int | None = None
|
||
staff_id: int | None = None
|
||
name: str
|
||
number: str | None = None
|
||
source_table: str # v_dim_assistant / v_dim_staff
|
||
|
||
|
||
class ApproveRequest(CamelModel):
|
||
"""审核通过请求。"""
|
||
role: str = Field(..., min_length=1, description="分配角色(coach/staff/head_coach/manager)")
|
||
assistant_id: int | None = Field(None, description="关联助教 ID")
|
||
staff_id: int | None = Field(None, description="关联员工 ID")
|
||
|
||
|
||
class RejectRequest(CamelModel):
|
||
"""审核拒绝请求。"""
|
||
reason: str = Field(..., min_length=1, description="拒绝原因")
|
||
|
||
|
||
# ── 用户管理 ──────────────────────────────────────────────
|
||
|
||
|
||
class UserListItem(CamelModel):
|
||
"""用户列表项。"""
|
||
id: int
|
||
nickname: str | None = None
|
||
role: str | None = None # 角色中文名(显示用)
|
||
role_code: str | None = None # 角色 code(提交用)
|
||
assistant_id: int | None = None # 当前绑定的助教 ID
|
||
staff_id: int | None = None # 当前绑定的员工 ID
|
||
assistant_name: str | None = None
|
||
site_name: str | None = None
|
||
site_id: int | None = None
|
||
status: str # approved / disabled
|
||
|
||
|
||
class UserEditRequest(CamelModel):
|
||
"""用户编辑请求(合并角色+绑定)。
|
||
|
||
角色与绑定互斥:coach 只能绑 assistant_id,其他角色只能绑 staff_id。
|
||
换角色时后端自动清除旧绑定。staffBinding="none" 表示解绑。
|
||
"""
|
||
role: str | None = Field(None, description="新角色 code(coach/staff/head_coach/manager)")
|
||
site_id: int | None = Field(None, description="新门店 ID")
|
||
assistant_id: int | None = Field(None, description="关联助教 ID(仅 coach 角色)")
|
||
staff_id: int | None = Field(None, description="关联员工 ID(仅非 coach 角色)")
|
||
# CHANGE 2026-03-23 | 移除 status 字段:租户不能禁用用户,只能移除店铺关系
|
||
# CHANGE 2026-03-24 | 合并绑定字段:角色+绑定同一请求提交,换角色自动清除旧绑定
|
||
|
||
|
||
class UserBindingRequest(CamelModel):
|
||
"""用户绑定修改请求。"""
|
||
assistant_id: int | None = Field(None, description="关联助教 ID")
|
||
staff_id: int | None = Field(None, description="关联员工 ID")
|
||
|
||
|
||
# ── 角色 + 人员候选 ──────────────────────────────────────
|
||
# [CHANGE P20260323-164500] intent: 审核弹窗角色动态化 + 人员联动所需的响应 Schema
|
||
# assumptions: StaffCandidate.source 区分 assistant/staff,前端据此构造 staffBinding 值
|
||
|
||
|
||
class RoleItem(CamelModel):
|
||
"""角色列表项(从 auth.roles 动态读取)。"""
|
||
id: int
|
||
code: str
|
||
name: str
|
||
description: str | None = None
|
||
|
||
|
||
class StaffCandidate(CamelModel):
|
||
"""人员候选项(审核弹窗关联下拉用)。"""
|
||
id: int = Field(..., description="assistant_id 或 staff_id")
|
||
identity_label: str | None = Field(None, description="身份角色(level / staff_identity 的原始值)")
|
||
name: str = Field(..., description="姓名")
|
||
mobile: str | None = Field(None, description="手机号")
|
||
entry_time: str | None = Field(None, description="入职时间")
|
||
source: str = Field(..., description="assistant / staff")
|