🎭 飞行侠实现:多身份登录系统

核心功能:
- 用户模型扩展:linked_agents 字段存储绑定龙虾
- 登录 API 支持 3 种模式:human_only / agent_only / both
- 龙虾管理 API:绑定/解绑/列表
- 扫描本机龙虾 API:从注册实例获取

API 端点:
- POST /api/v1/auth/login/ - 支持 login_mode 和 selected_agent_id
- GET  /api/v1/user/linked-agents/ - 获取绑定龙虾
- POST /api/v1/user/linked-agents/ - 添加绑定龙虾
- DELETE /api/v1/user/linked-agents/{id}/ - 移除龙虾
- GET  /api/v1/user/scan-local-agents/ - 扫描本机龙虾

登录模式:
1. human_only - 纯人类身份(1 个座位)
2. agent_only - 纯龙虾身份(1 个座位)
3. both - 双重身份(2 个座位)

测试:
- test_multi_identity.py: 完整测试通过

使用场景:
- 普通用户参会 → human_only
- 龙虾独立参会 → agent_only
- 用户带龙虾助理 → both
This commit is contained in:
2026-04-04 12:53:02 +08:00
parent 9a30cc3945
commit 97da46b219
6 changed files with 471 additions and 6 deletions

View File

@@ -133,6 +133,9 @@ STATIC_URL = "static/"
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
# 自定义用户模型
AUTH_USER_MODEL = 'users.User'
# REST Framework 配置
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [],

View File

@@ -3,7 +3,7 @@ from django.urls import path, include, re_path
from django.views.generic import TemplateView
from rest_framework.routers import DefaultRouter
from meetings.views import MeetingViewSet, ParticipantViewSet
from users.views import LoginView, RegisterView
from users.views import LoginView, RegisterView, LinkedAgentsView, ScanLocalAgentsView
from instances.views import InstanceRegisterView, MeetingJoinView, InstanceListView, WebhookNotifyView
from meetings.minutes_api import MeetingRecordsView, MinutesUploadView, MeetingEndNotifyView
@@ -16,6 +16,11 @@ urlpatterns = [
path("", TemplateView.as_view(template_name="meeting_room.html"), name="home"),
path("api/v1/auth/login/", LoginView.as_view()),
path("api/v1/auth/register/", RegisterView.as_view()),
# 用户龙虾管理
path("api/v1/user/linked-agents/", LinkedAgentsView.as_view()),
path("api/v1/user/linked-agents/<str:agent_id>/", LinkedAgentsView.as_view()),
path("api/v1/user/scan-local-agents/", ScanLocalAgentsView.as_view()),
# 实例管理
path("api/v1/instances/register/", InstanceRegisterView.as_view()),
path("api/v1/instances/join-meeting/", MeetingJoinView.as_view()),
path("api/v1/instances/", InstanceListView.as_view()),