feat(admin): Phase 1 注册邀请码逻辑 — 码必填 + kind 分流 + validate-invite + 注册页码优先重做

后端:Invitation.kind(join_team/create_team)+ team 可空 + migration;RegisterSerializer 邀请码必填,
create_team 开新团队当 owner+发试用额度、join_team 幂等入伙不重复发额度,删「空码开团队」;
validate-invite 免登录验码端点;团管发码恒 join_team;InvitationSerializer 增 kind/team_name。
前端:注册页码优先(验过才展开;create_team 填团队名 / join_team 只读团队名,不暴露团队列表)、
邀请链接 ?invite= 自动验码、api.validateInvite、验码行/状态提示样式(仅 token)。
测试:accounts 22/22 单测过(RegisterInviteCodeTests + ValidateInviteTests);
无头 e2e _admin-p1.mjs 全断言过 + 0 console error;tsc+build 绿。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
seaislee1209
2026-06-19 21:07:03 +08:00
co-authored by Claude Opus 4.8
parent 443023a1a9
commit 3f8547564c
12 changed files with 684 additions and 172 deletions
@@ -0,0 +1,24 @@
# Generated by Django 5.1.15 on 2026-06-19 12:54
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0004_user_is_platform_admin_adminauditlog'),
]
operations = [
migrations.AddField(
model_name='invitation',
name='kind',
field=models.CharField(choices=[('join_team', 'Join Team'), ('create_team', 'Create Team')], default='join_team', max_length=16),
),
migrations.AlterField(
model_name='invitation',
name='team',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='invitations', to='accounts.team'),
),
]