""" 设备模块模型 """ from django.db import models from apps.users.models import User from apps.spirits.models import Spirit class DeviceType(models.Model): """设备类型表""" id = models.BigAutoField(primary_key=True) brand = models.CharField('品牌', max_length=50) product_code = models.CharField('产品代号', max_length=50, unique=True) name = models.CharField('名称', max_length=100) is_network_required = models.BooleanField('是否需要联网', default=True) is_active = models.BooleanField('是否启用', default=True) created_at = models.DateTimeField('创建时间', auto_now_add=True) updated_at = models.DateTimeField('更新时间', auto_now=True) class Meta: db_table = 'device_type' verbose_name = '设备类型' verbose_name_plural = '设备类型' def save(self, *args, **kwargs): # 根据产品代号后缀自动判断是否需要联网 if self.product_code: self.is_network_required = not self.product_code.endswith('-OFF') super().save(*args, **kwargs) def __str__(self): return f"{self.brand} - {self.name}" class DeviceBatch(models.Model): """设备批次表""" STATUS_CHOICES = [ ('pending', '待生成'), ('generated', '已生成'), ] id = models.BigAutoField(primary_key=True) device_type = models.ForeignKey(DeviceType, on_delete=models.PROTECT, related_name='batches', verbose_name='设备类型') batch_no = models.CharField('批次号', max_length=50) production_date = models.DateField('生产日期') production_week = models.CharField('生产周', max_length=10, blank=True) # 格式: 25W45 quantity = models.IntegerField('数量') remark = models.TextField('备注', blank=True, default='') status = models.CharField('状态', max_length=20, choices=STATUS_CHOICES, default='pending') created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose_name='创建人') created_at = models.DateTimeField('创建时间', auto_now_add=True) updated_at = models.DateTimeField('更新时间', auto_now=True) class Meta: db_table = 'device_batch' verbose_name = '设备批次' verbose_name_plural = '设备批次' unique_together = ['device_type', 'batch_no', 'production_date'] def save(self, *args, **kwargs): # 计算生产周 if self.production_date and not self.production_week: year = self.production_date.year week = self.production_date.isocalendar()[1] self.production_week = f"{year % 100}W{week:02d}" super().save(*args, **kwargs) def __str__(self): return f"{self.device_type.brand}-{self.batch_no}" class Device(models.Model): """设备表""" STATUS_CHOICES = [ ('in_stock', '库存中'), ('out_stock', '已出库'), ('bound', '已绑定'), ] id = models.BigAutoField(primary_key=True) sn = models.CharField('SN码', max_length=50, unique=True) device_type = models.ForeignKey(DeviceType, on_delete=models.PROTECT, null=True, related_name='devices', verbose_name='设备类型') batch = models.ForeignKey(DeviceBatch, on_delete=models.SET_NULL, null=True, related_name='devices', verbose_name='所属批次') mac_address = models.CharField('MAC地址', max_length=20, blank=True, null=True, unique=True) name = models.CharField('自定义名称', max_length=100, blank=True, default='') status = models.CharField('状态', max_length=20, choices=STATUS_CHOICES, default='in_stock') battery = models.IntegerField('电量百分比', default=0) # 0-100 is_online = models.BooleanField('是否在线', default=False) is_ai = models.BooleanField('是否AI设备', default=True) icon = models.CharField('设备图标', max_length=100, null=True, blank=True) firmware_version = models.CharField('固件版本', max_length=20, blank=True, default='') last_online_at = models.DateTimeField('最后在线时间', null=True, blank=True) created_at = models.DateTimeField('创建时间', auto_now_add=True) updated_at = models.DateTimeField('更新时间', auto_now=True) class Meta: db_table = 'device' verbose_name = '设备' verbose_name_plural = '设备' indexes = [ models.Index(fields=['mac_address']), models.Index(fields=['status']), ] def __str__(self): return self.sn class UserDevice(models.Model): """用户设备绑定表""" BIND_TYPE_CHOICES = [ ('owner', '所有者'), ('share', '分享'), ] id = models.BigAutoField(primary_key=True) user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_devices', verbose_name='用户') device = models.ForeignKey(Device, on_delete=models.CASCADE, related_name='user_devices', verbose_name='设备') spirit = models.ForeignKey(Spirit, on_delete=models.SET_NULL, null=True, blank=True, related_name='user_devices', verbose_name='绑定的智能体') bind_type = models.CharField('绑定类型', max_length=20, choices=BIND_TYPE_CHOICES, default='owner') bind_time = models.DateTimeField('绑定时间', auto_now_add=True) is_active = models.BooleanField('是否有效', default=True) class Meta: db_table = 'user_device' verbose_name = '用户设备绑定' verbose_name_plural = '用户设备绑定' unique_together = ['user', 'device'] def __str__(self): return f"{self.user.phone} - {self.device.sn}" class DeviceSettings(models.Model): """设备设置""" device = models.OneToOneField( Device, on_delete=models.CASCADE, related_name='settings', verbose_name='设备' ) nickname = models.CharField('设备昵称', max_length=50, null=True, blank=True) user_name = models.CharField('用户称呼', max_length=50, null=True, blank=True) volume = models.IntegerField('音量', default=50) # 0-100 brightness = models.IntegerField('亮度', default=50) # 0-100 allow_interrupt = models.BooleanField('允许打断', default=True) privacy_mode = models.BooleanField('隐私模式', default=False) created_at = models.DateTimeField('创建时间', auto_now_add=True) updated_at = models.DateTimeField('更新时间', auto_now=True) class Meta: db_table = 'device_settings' verbose_name = '设备设置' verbose_name_plural = verbose_name def __str__(self): return f"设置 - {self.device.sn}" class DeviceWifi(models.Model): """设备 WiFi 配置""" device = models.ForeignKey( Device, on_delete=models.CASCADE, related_name='wifi_list', verbose_name='设备' ) ssid = models.CharField('WiFi名称', max_length=100) is_connected = models.BooleanField('是否已连接', default=False) created_at = models.DateTimeField('创建时间', auto_now_add=True) updated_at = models.DateTimeField('更新时间', auto_now=True) class Meta: db_table = 'device_wifi' verbose_name = '设备WiFi' verbose_name_plural = verbose_name unique_together = ['device', 'ssid'] def __str__(self): return f"{self.device.sn} - {self.ssid}"