ai_admin/WebAdmin/models.py
2024-09-20 04:29:09 +00:00

235 lines
13 KiB
Python
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from datetime import datetime, timedelta
import random
import string
from django.contrib.auth.models import AbstractUser
from django.db import models
from datetime import datetime
def generate_unique_referral_code():
while True:
referral_code = ''.join(random.choices(string.ascii_uppercase + string.digits, k=8))
if not User.objects.filter(referral_code=referral_code).exists():
return referral_code
class User(AbstractUser):
phone = models.CharField(max_length=20, unique=True, null=True, blank=True) # 手机号,唯一,可以为空
google_id = models.CharField(max_length=50, unique=True, null=True, blank=True) # Google ID唯一可以为空
is_member = models.BooleanField(default=False) # 是否是会员
points = models.IntegerField(default=0) # 用户积分
invited_by = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True, related_name='invitees') # 邀请人
referral_code = models.CharField(max_length=50, unique=True) # 推荐码,唯一
commission_rate = models.DecimalField(max_digits=5, decimal_places=2, default=0.00) # 返佣比例
created_at = models.DateTimeField(default=datetime.now) # 创建时间
updated_at = models.DateTimeField(auto_now=True) # 更新时间
login_count = models.IntegerField(default=0) # 登录次数
last_login_ip = models.GenericIPAddressField(null=True, blank=True) # 最后登录IP
membership_start = models.DateTimeField(null=True, blank=True) # 会员开始时间
membership_end = models.DateTimeField(null=True, blank=True) # 会员到期时间
openid_used = models.CharField(max_length=150, null=True, blank=True, unique=True) # 已用的 openid确保每个 openid 只能使用一次
source = models.CharField(max_length=50, default='web') # 用户来源,默认为 'web'
def save(self, *args, **kwargs):
if not self.referral_code:
self.referral_code = generate_unique_referral_code()
super().save(*args, **kwargs)
def __str__(self):
return self.username
class Referral(models.Model):
referrer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='referrals_made') # 邀请人ID外键引用User模型
referee = models.ForeignKey(User, on_delete=models.CASCADE, related_name='referrals_received') # 被邀请人ID外键引用User模型
commission_amount = models.DecimalField(max_digits=10, decimal_places=2) # 返佣金额最大值为99999999.99
created_at = models.DateTimeField(default=datetime.now) # 创建时间,默认当前时间
def __str__(self):
return f'{self.referrer} invited {self.referee}'
class UserSource(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE) # 用户ID外键引用User模型
source = models.CharField(max_length=50) # 用户来源最大长度50
created_at = models.DateTimeField(default=datetime.now) # 创建时间,默认当前时间
def __str__(self):
return f'{self.user} - {self.source}'
class SMSVerificationCode(models.Model):
phone_number = models.CharField(max_length=15) # 手机号
code = models.CharField(max_length=6) # 验证码
created_at = models.DateTimeField(auto_now_add=True) # 创建时间,自动设置为当前时间
is_used = models.BooleanField(default=False) # 是否已使用
def is_expired(self):
return self.created_at < datetime.now() - timedelta(minutes=5) # 判断验证码是否已过期
def __str__(self):
return f"{self.phone_number} - {self.code}"
class EmailVerificationCode(models.Model):
email = models.EmailField() # 邮箱地址
code = models.CharField(max_length=6) # 验证码
created_at = models.DateTimeField(auto_now_add=True) # 创建时间,自动设置为当前时间
is_used = models.BooleanField(default=False) # 是否已使用
def is_expired(self):
return self.created_at < datetime.now() - timedelta(minutes=5) # 判断验证码是否已过期
def __str__(self):
return f"{self.email} - {self.code}"
class VideoGeneration(models.Model):
STATUS_CHOICES = [
('pending', 'Pending'),
('in_progress', 'In Progress'),
('completed', 'Completed'),
('failed', 'Failed'),
]
video_id = models.CharField(max_length=255, unique=True, default='')
user = models.ForeignKey(User, on_delete=models.CASCADE) # 生成请求的用户
text = models.TextField(null=True) # 输入文本
voice_name = models.CharField(max_length=50, null=True) # 选择的语音
style = models.CharField(max_length=50, default='general', null=True) # 语音风格
rate = models.IntegerField(default=0, null=True) # 语速
media_type = models.CharField(max_length=50, null=True) # 媒体类型
ratio = models.CharField(max_length=10) # 视频比例
audio_url = models.URLField(null=True, blank=True) # 生成的音频URL
video_url = models.URLField(null=True, blank=True) # 生成的视频URL
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending') # 生成状态
created_at = models.DateTimeField(default=datetime.now) # 创建时间
updated_at = models.DateTimeField(auto_now=True) # 更新时间
slug = models.CharField(max_length=50) # 生成视频的类型
pid = models.CharField(max_length=50, null=True, default='') # 生成视频的ID
extension_count = models.IntegerField(default=0) # 延长次数最多3次
time_duration = models.IntegerField(default=0) # 生成时长
def __str__(self):
return f'{self.video_id} - {self.user.username} - {self.status} - {self.created_at}'
class Plan(models.Model):
"""
存放套餐信息的数据库模型
"""
title = models.CharField(max_length=100, unique=True) # 套餐标题,标识套餐的名称(如 HOBBY、GROWTH、GROWTH PLUS
description = models.TextField() # 套餐描述,详细说明套餐中包含的所有功能和服务
price = models.DecimalField(max_digits=10, decimal_places=2) # 套餐价格,表示套餐的费用,保留两位小数
credits_per_month = models.IntegerField(default=0) # 每月积分,套餐中包含的每月 AI 积分数
created_at = models.DateTimeField(default=datetime.now) # 创建时间,记录套餐的创建时间
updated_at = models.DateTimeField(auto_now=True) # 更新时间,记录套餐信息的最后更新时间
is_promotional = models.BooleanField(default=False) # 是否为促销活动,用于标识该套餐是否属于促销套餐
unlimited_exports = models.BooleanField(default=False) # 是否允许无限导出功能,适用于一些高级套餐
smart_music_sync = models.BooleanField(default=False) # 是否包含智能音乐同步功能,用于标识该套餐是否包含此项服务
def __str__(self):
return self.title
class Order(models.Model):
PAYMENT_METHOD_CHOICES = [
('alipay', 'Alipay'),
('paypal', 'PayPal'),
]
ORDER_STATUS_CHOICES = [
('pending', 'Pending'),
('completed', 'Completed'),
('canceled', 'Canceled'),
('failed', 'Failed'),
]
order_id = models.CharField(max_length=100, unique=True) # 订单唯一标识符
user = models.ForeignKey('User', on_delete=models.CASCADE) # 用户外键
username = models.CharField(max_length=150) # 用户名(邮箱或手机号)
plan = models.ForeignKey('Plan', on_delete=models.CASCADE) # 关联套餐
amount = models.DecimalField(max_digits=10, decimal_places=2,default=0.00) # 订单金额
payment_method = models.CharField(max_length=10, choices=PAYMENT_METHOD_CHOICES) # 支付方式
status = models.CharField(max_length=10, choices=ORDER_STATUS_CHOICES, default='pending') # 订单状态
created_at = models.DateTimeField(default=datetime.now) # 创建时间
updated_at = models.DateTimeField(auto_now=True) # 更新时间
def __str__(self):
return f"Order {self.order_id} - {self.status}"
class Meta:
verbose_name = 'Order'
verbose_name_plural = 'Orders'
ordering = ['-created_at']
class TransactionHistory(models.Model):
"""
记录用户的积分消费明细
"""
FEATURE_CHOICES = [
('text-to-video', 'AI文生视频'),
('img-to-video', 'AI图生视频'),
('create-tiktok-video', 'AI长视频生成'),
('music-to-video', '音乐视频生成'),
('create-avatar-video', '虚拟形象视频生成'),
]
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='transactions', verbose_name='用户') # 关联用户
feature = models.CharField(max_length=50, choices=FEATURE_CHOICES, verbose_name='功能类型') # 功能类型
points_spent = models.IntegerField(verbose_name='消费积分') # 消费的积分数量
char_count = models.IntegerField(blank=True, null=True, verbose_name='字符数量') # 记录字符数量(如果是文本相关的功能)
description = models.TextField(blank=True, null=True, verbose_name='操作描述') # 记录操作的详细描述
transaction_date = models.DateTimeField(default=datetime.now, verbose_name='消费时间') # 消费时间
previous_points_balance = models.IntegerField(verbose_name='消费前积分') # 用户消费前的积分余额
new_points_balance = models.IntegerField(verbose_name='消费后积分') # 用户消费后的积分余额
success = models.BooleanField(default=True, verbose_name='是否成功') # 记录是否成功扣费
class Meta:
db_table = 'transaction_history'
verbose_name = '消费明细'
verbose_name_plural = '消费明细'
ordering = ['-transaction_date'] # 按消费时间倒序排列
def __str__(self):
return f'用户 {self.user.username} 消费 {self.points_spent} 积分 ({self.feature})'
class WebsiteInfo(models.Model):
"""
用于存储网站的域名、标题、关键词和描述,包括中英文版本。
"""
domain_en = models.CharField(max_length=255,default=True, verbose_name='域名') # 网站域名
domain_zh = models.CharField(max_length=255,default=True, verbose_name='域名') # 网站域名
title_en = models.CharField(max_length=255,default=True, verbose_name='英文标题') # 英文标题
title_zh = models.CharField(max_length=255,default=True, verbose_name='中文标题') # 中文标题
keywords_en = models.TextField(verbose_name='英文关键词',default=True) # 英文关键词
keywords_zh = models.TextField(verbose_name='中文关键词',default=True) # 中文关键词
description_en = models.TextField(verbose_name='英文描述',default=True) # 英文描述
description_zh = models.TextField(verbose_name='中文描述',default=True) # 中文描述
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') # 创建时间
updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间') # 更新时间
class Meta:
db_table = 'website_info'
verbose_name = '网站信息'
verbose_name_plural = '网站信息'
ordering = ['-created_at'] # 按照创建时间倒序排列
class WebsiteAccessLog(models.Model):
"""
用于记录网站访问的IP、浏览器语言、来源URL、请求路径、访问时间等信息。
"""
ip_address = models.GenericIPAddressField(verbose_name='访问IP')
browser_language = models.CharField(max_length=200, verbose_name='浏览器语言', blank=True, null=True)
referrer = models.TextField(verbose_name='来源URL', blank=True, null=True)
request_path = models.CharField(max_length=255, verbose_name='请求路径')
request_method = models.CharField(max_length=10, verbose_name='请求方法')
user_agent = models.TextField(verbose_name='用户代理', blank=True, null=True)
device_type = models.CharField(max_length=50, verbose_name='设备类型', blank=True, null=True)
access_time = models.DateTimeField(verbose_name='访问时间', auto_now_add=True)
access_time_bj = models.DateTimeField(verbose_name='北京时间', blank=True, null=True)
access_date = models.DateField(verbose_name='访问日期', blank=True, null=True)
class Meta:
db_table = 'website_access_log'
verbose_name = '网站访问日志'
verbose_name_plural = '网站访问日志'
unique_together = ('ip_address', 'access_date') # 确保同一IP在同一天只能记录一次
def __str__(self):
access_time_str = self.access_time_bj.strftime('%Y-%m-%d %H:%M:%S') if self.access_time_bj else 'N/A'
return f"{self.ip_address} - {access_time_str}"