from django.db import models from django.contrib.auth.models import User import uuid import os import json def get_file_path(instance, filename): """为上传的文件生成唯一的文件路径""" ext = filename.split('.')[-1] filename = f"{uuid.uuid4()}.{ext}" return os.path.join(f'users/{instance.project.user.id}/projects/{instance.project.id}/data/', filename) def get_export_file_path(instance, filename): """为导出的文件生成唯一的文件路径""" ext = filename.split('.')[-1] filename = f"{uuid.uuid4()}.{ext}" return os.path.join(f'users/{instance.project.user.id}/projects/{instance.project.id}/exports/', filename) # class ThirdPartyUserMapping(models.Model): # """第三方用户映射模型""" # user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='third_party_mapping') # third_party_user_id = models.IntegerField('第三方用户ID', unique=True) # third_party_username = models.CharField('第三方用户名', max_length=255) # created_at = models.DateTimeField('创建时间', auto_now_add=True) # updated_at = models.DateTimeField('更新时间', auto_now=True) # class Meta: # verbose_name = '第三方用户映射' # verbose_name_plural = '第三方用户映射' # def __str__(self): # return f"{self.third_party_username} ({self.third_party_user_id}) -> {self.user.username}" # class TokenStorage(models.Model): # """Token存储模型""" # token = models.CharField('Token', max_length=512, unique=True) # user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='tokens') # third_party_user_id = models.IntegerField('第三方用户ID') # third_party_username = models.CharField('第三方用户名', max_length=255) # created_at = models.DateTimeField('创建时间', auto_now_add=True) # last_used = models.DateTimeField('最后使用时间', auto_now=True) # expires_at = models.DateTimeField('过期时间', null=True, blank=True) # class Meta: # verbose_name = 'Token存储' # verbose_name_plural = 'Token存储' # indexes = [ # models.Index(fields=['token']), # models.Index(fields=['third_party_user_id']), # ] # def __str__(self): # return f"Token for {self.third_party_username} ({self.third_party_user_id})" class Project(models.Model): """项目模型""" STATUS_CHOICES = ( ('initialized', '已初始化'), ('data_loaded', '数据已加载'), ('preprocessing', '数据预处理中'), ('preprocessing_completed', '数据预处理完成'), ('analysis', '分析中'), ('completed', '已完成'), ('error', '出错'), ) id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField('项目名称', max_length=200) description = models.TextField('项目描述', blank=True) user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='projects') created_at = models.DateTimeField('创建时间', auto_now_add=True) last_modified = models.DateTimeField('最后修改时间', auto_now=True) status = models.CharField('项目状态', max_length=50, choices=STATUS_CHOICES, default='initialized') active_data_file = models.ForeignKey('DataFile', on_delete=models.SET_NULL, related_name='active_in_projects', null=True, blank=True, verbose_name='当前活动数据文件') class Meta: verbose_name = '项目' verbose_name_plural = '项目' def __str__(self): return self.name class DataFile(models.Model): """数据文件模型""" project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='data_files') file = models.FileField('文件', upload_to=get_file_path) filename = models.CharField('文件名', max_length=255) uploaded_at = models.DateTimeField('上传时间', auto_now_add=True) wavenumber_min = models.FloatField('最小波数', null=True, blank=True) wavenumber_max = models.FloatField('最大波数', null=True, blank=True) group_index = models.IntegerField('分组索引', default=2, null=True, blank=True) class Meta: verbose_name = '数据文件' verbose_name_plural = '数据文件' def __str__(self): return self.filename class PreprocessingTask(models.Model): """预处理任务模型""" project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='preprocessing_tasks') created_at = models.DateTimeField('创建时间', auto_now_add=True) completed_at = models.DateTimeField('完成时间', null=True, blank=True) parameters = models.JSONField('参数', default=dict) status = models.CharField('状态', max_length=50, default='pending') result = models.JSONField('结果', null=True, blank=True) class Meta: verbose_name = '预处理任务' verbose_name_plural = '预处理任务' def __str__(self): return f"{self.project.name} - 预处理任务 {self.id}" class AnalysisTask(models.Model): """分析任务模型""" ANALYSIS_TYPE_CHOICES = ( ('meta_free', '无元数据分析'), ('meta_based', '基于元数据分析'), ) project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='analysis_tasks') analysis_type = models.CharField('分析类型', max_length=20, choices=ANALYSIS_TYPE_CHOICES) created_at = models.DateTimeField('创建时间', auto_now_add=True) completed_at = models.DateTimeField('完成时间', null=True, blank=True) parameters = models.JSONField('参数', default=dict) status = models.CharField('状态', max_length=50, default='pending') result = models.JSONField('结果', null=True, blank=True) class Meta: verbose_name = '分析任务' verbose_name_plural = '分析任务' def __str__(self): return f"{self.project.name} - {self.get_analysis_type_display()} 任务 {self.id}" class ExportTask(models.Model): """导出任务模型""" project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='export_tasks') created_at = models.DateTimeField('创建时间', auto_now_add=True) completed_at = models.DateTimeField('完成时间', null=True, blank=True) format = models.CharField('格式', max_length=10) components = models.JSONField('组件', default=list) status = models.CharField('状态', max_length=50, default='pending') file = models.FileField('导出文件', upload_to=get_export_file_path, null=True, blank=True) class Meta: verbose_name = '导出任务' verbose_name_plural = '导出任务' def __str__(self): return f"{self.project.name} - 导出任务 {self.id}"