XinXiKuaiBaoYuan/django-backend/tasks/models.py

184 lines
7.2 KiB
Python
Raw 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 django.db import models
from django.contrib.auth.models import User
import json
class Task(models.Model):
"""任务模型"""
TASK_TYPES = [
('single', '单次任务'),
('scheduled', '周期任务'),
]
TASK_STATUSES = [
('running', '运行中'), # 当前任务在运行
('generating', '生成中'), # 当前任务有报告正在生成
('error', '异常'), # 报告生成异常
('paused', '暂停'), # 任务暂停
]
title = models.CharField(max_length=255, verbose_name='任务标题')
description = models.TextField(blank=True, verbose_name='任务描述')
requirement = models.TextField(verbose_name='用户需求描述')
type = models.CharField(max_length=20, choices=TASK_TYPES, verbose_name='任务类型')
status = models.CharField(max_length=20, choices=TASK_STATUSES, default='running', verbose_name='任务状态')
# JSON字段存储配置
schedule_config = models.JSONField(null=True, blank=True, verbose_name='周期任务配置')
sources_config = models.JSONField(default=dict, verbose_name='信息源配置')
web_search_enabled = models.BooleanField(default=True, verbose_name='是否启用联网搜索')
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='用户')
# 时间字段
last_report_time = models.DateTimeField(null=True, blank=True, verbose_name='最新报告生成时间')
next_run_time = models.DateTimeField(null=True, blank=True, verbose_name='下次执行时间')
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'tasks'
verbose_name = '任务'
verbose_name_plural = '任务'
ordering = ['-last_report_time', '-created_at']
indexes = [
models.Index(fields=['user', 'status']),
models.Index(fields=['last_report_time']),
models.Index(fields=['status']),
]
def __str__(self):
return f"{self.title} ({self.get_type_display()})"
@property
def report_count(self):
"""获取报告数量"""
return self.reports.count()
@property
def has_new_report(self):
"""是否有新报告(用于排序)"""
if not self.last_report_time:
return False
# 如果最新报告是24小时内生成的认为是新报告
from django.utils import timezone
from datetime import timedelta
return timezone.now() - self.last_report_time < timedelta(hours=24)
class Report(models.Model):
"""报告模型"""
REPORT_STATUSES = [
('generating', '生成中'),
('completed', '已完成'),
('failed', '失败'),
]
task = models.ForeignKey(Task, on_delete=models.CASCADE, related_name='reports', verbose_name='任务')
title = models.CharField(max_length=255, verbose_name='报告标题')
summary = models.TextField(blank=True, verbose_name='报告摘要')
content = models.TextField(verbose_name='报告内容')
source_tag = models.CharField(max_length=100, blank=True, verbose_name='信息来源标签')
word_count = models.IntegerField(default=0, verbose_name='字数统计')
status = models.CharField(max_length=20, choices=REPORT_STATUSES, default='generating', verbose_name='生成状态')
generated_at = models.DateTimeField(null=True, blank=True, verbose_name='生成完成时间')
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'reports'
verbose_name = '报告'
verbose_name_plural = '报告'
ordering = ['-generated_at', '-created_at']
indexes = [
models.Index(fields=['task', 'generated_at']),
models.Index(fields=['status']),
models.Index(fields=['generated_at']),
]
def __str__(self):
return f"{self.title} - {self.task.title}"
def save(self, *args, **kwargs):
# 自动计算字数
if self.content:
self.word_count = len(self.content.replace(' ', '').replace('\n', ''))
# 如果状态变为完成,更新生成时间和任务的最新报告时间
if self.status == 'completed' and not self.generated_at:
from django.utils import timezone
self.generated_at = timezone.now()
self.task.last_report_time = self.generated_at
self.task.save(update_fields=['last_report_time'])
super().save(*args, **kwargs)
class ReportSource(models.Model):
"""报告来源数据模型"""
SOURCE_TYPES = [
('wechat', '微信'),
('official-account', '公众号'),
('feishu', '飞书'),
('dingtalk', '钉钉'),
('email', '邮箱'),
('website', '网页'),
('baidu-pan', '百度网盘'),
('web-search', '联网搜索'),
]
report = models.ForeignKey(Report, on_delete=models.CASCADE, related_name='sources', verbose_name='报告')
source_type = models.CharField(max_length=20, choices=SOURCE_TYPES, verbose_name='信息源类型')
source_name = models.CharField(max_length=255, verbose_name='信息源名称')
source_url = models.URLField(blank=True, verbose_name='原始链接')
raw_content = models.TextField(blank=True, verbose_name='原始内容')
extracted_content = models.TextField(blank=True, verbose_name='提取的关键内容')
collected_at = models.DateTimeField(auto_now_add=True, verbose_name='采集时间')
class Meta:
db_table = 'report_sources'
verbose_name = '报告来源数据'
verbose_name_plural = '报告来源数据'
indexes = [
models.Index(fields=['report']),
models.Index(fields=['source_type']),
]
def __str__(self):
return f"{self.source_name} - {self.report.title}"
class TaskLog(models.Model):
"""任务执行日志模型"""
ACTION_TYPES = [
('created', '创建'),
('started', '开始'),
('paused', '暂停'),
('resumed', '恢复'),
('completed', '完成'),
('error', '错误'),
]
task = models.ForeignKey(Task, on_delete=models.CASCADE, related_name='logs', verbose_name='任务')
action_type = models.CharField(max_length=20, choices=ACTION_TYPES, verbose_name='操作类型')
message = models.TextField(blank=True, verbose_name='日志信息')
error_details = models.JSONField(null=True, blank=True, verbose_name='错误详情')
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
class Meta:
db_table = 'task_logs'
verbose_name = '任务执行日志'
verbose_name_plural = '任务执行日志'
ordering = ['-created_at']
indexes = [
models.Index(fields=['task', 'created_at']),
models.Index(fields=['action_type']),
]
def __str__(self):
return f"{self.task.title} - {self.get_action_type_display()}"