from django.db import models from django.conf import settings from card.storage import OSSStorage # 初始化OSS存储,指定achievements目录 oss_storage = OSSStorage(base_dir='achievements') class Achievement(models.Model): """ 成就模型 存储各种成就的基本信息和获取条件 """ name = models.CharField('成就名称', max_length=100) description = models.TextField('成就描述') icon = models.ImageField( '成就图标', upload_to='icons/', storage=oss_storage, null=True, blank=True ) conditions = models.JSONField('获取条件', help_text='JSON格式的成就获取条件') # 成就等级/稀有度 RARITY_CHOICES = ( ('common', '普通'), ('precious', '珍贵'), ('rare', '稀有'), ('epic', '史诗'), ('legendary', '传说'), ) rarity = models.CharField('稀有度', max_length=20, choices=RARITY_CHOICES, default='common') # 成就类型分类 TYPE_CHOICES = ( ('login', '登录相关'), ('activity', '活动相关'), ('social', '社交相关'), ('usage', '使用相关'), ('special', '特殊成就'), ('hidden', '隐藏成就'), ) achievement_type = models.CharField('成就类型', max_length=20, choices=TYPE_CHOICES, default='special') # 是否为隐藏成就(不在成就列表中显示,直到获得) is_hidden = models.BooleanField('隐藏成就', default=False) # 成就积分(获得该成就奖励的积分) points = models.IntegerField('成就积分', default=0) created_at = models.DateTimeField('创建时间', auto_now_add=True) updated_at = models.DateTimeField('更新时间', auto_now=True) class Meta: verbose_name = '成就' verbose_name_plural = '成就' ordering = ['rarity', 'name'] indexes = [ models.Index(fields=['name']), models.Index(fields=['achievement_type']), models.Index(fields=['rarity']), ] def __str__(self): return self.name class UserAchievement(models.Model): """ 用户成就关联模型 记录用户获得的成就信息 """ user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='achievements', verbose_name='用户' ) achievement = models.ForeignKey( Achievement, on_delete=models.CASCADE, related_name='users', verbose_name='成就' ) acquired_at = models.DateTimeField('获得时间', auto_now_add=True) # 如果需要存储获得成就时的特定数据 acquisition_data = models.JSONField('获得数据', null=True, blank=True, help_text='JSON格式的获得成就时的相关数据') # 是否已显示通知(用于控制成就获得的通知提醒) notification_shown = models.BooleanField('已显示通知', default=False) class Meta: verbose_name = '用户成就' verbose_name_plural = '用户成就' ordering = ['-acquired_at'] # 确保一个用户不会重复获得同一个成就 unique_together = ['user', 'achievement'] indexes = [ models.Index(fields=['user']), models.Index(fields=['achievement']), models.Index(fields=['acquired_at']), ] def __str__(self): return f"{self.user} - {self.achievement}"