from django.contrib.auth.models import AbstractUser from django.db import models class Team(models.Model): """团队模型 — 额度管理的核心单位。""" name = models.CharField(max_length=100, unique=True, verbose_name='团队名称') total_seconds_pool = models.BigIntegerField(default=0, verbose_name='总额度池(秒)') total_seconds_used = models.FloatField(default=0, verbose_name='已消耗总秒数') monthly_seconds_limit = models.IntegerField(default=6000, verbose_name='每月消费上限(秒)') daily_member_limit_default = models.IntegerField(default=600, verbose_name='新成员默认每日限额(秒)') is_active = models.BooleanField(default=True, verbose_name='启用状态') created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间') class Meta: verbose_name = '团队' verbose_name_plural = '团队' def __str__(self): return self.name @property def remaining_seconds(self): return self.total_seconds_pool - self.total_seconds_used class User(AbstractUser): """Extended user model — Phase 5: team-based quota.""" email = models.EmailField(unique=True, verbose_name='邮箱') team = models.ForeignKey( Team, on_delete=models.SET_NULL, null=True, blank=True, related_name='members', verbose_name='所属团队', ) is_team_admin = models.BooleanField(default=False, verbose_name='团队管理员') daily_seconds_limit = models.IntegerField(default=600, verbose_name='每日秒数上限') monthly_seconds_limit = models.IntegerField(default=6000, verbose_name='每月秒数上限') created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间') class Meta: verbose_name = '用户' verbose_name_plural = '用户' def __str__(self): return self.username @property def role(self): if self.is_staff and self.team is None: return 'super_admin' if self.is_team_admin and self.team is not None: return 'team_admin' return 'member' class AdminAuditLog(models.Model): """管理员操作审计日志""" ACTION_CHOICES = [ ('team_create', '创建团队'), ('team_update', '更新团队'), ('team_topup', '团队充值'), ('team_set_pool', '设置团队额度池'), ('team_create_admin', '创建团队管理员'), ('user_create', '创建用户'), ('user_quota_update', '更新用户额度'), ('user_status_toggle', '切换用户状态'), ('settings_update', '更新系统设置'), ('member_create', '创建团队成员'), ('member_quota_update', '更新成员额度'), ('member_status_toggle', '切换成员状态'), ] operator = models.ForeignKey( User, on_delete=models.SET_NULL, null=True, related_name='audit_logs', verbose_name='操作人', ) operator_name = models.CharField(max_length=150, verbose_name='操作人用户名') action = models.CharField(max_length=30, choices=ACTION_CHOICES, verbose_name='操作类型') target_type = models.CharField(max_length=20, verbose_name='目标类型') target_id = models.IntegerField(null=True, blank=True, verbose_name='目标ID') target_name = models.CharField(max_length=200, blank=True, default='', verbose_name='目标名称') before = models.JSONField(null=True, blank=True, verbose_name='变更前') after = models.JSONField(null=True, blank=True, verbose_name='变更后') ip_address = models.GenericIPAddressField(null=True, blank=True, verbose_name='IP地址') created_at = models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='操作时间') class Meta: verbose_name = '审计日志' verbose_name_plural = '审计日志' ordering = ['-created_at'] def __str__(self): return f'{self.operator_name} - {self.get_action_display()} - {self.target_name}' def log_admin_action(request, action, target_type, target_id=None, target_name='', before=None, after=None): """记录管理员操作日志""" ip = request.META.get('HTTP_X_FORWARDED_FOR', '').split(',')[0].strip() or request.META.get('REMOTE_ADDR') AdminAuditLog.objects.create( operator=request.user, operator_name=request.user.username, action=action, target_type=target_type, target_id=target_id, target_name=target_name, before=before, after=after, ip_address=ip, )