1336 lines
54 KiB
Python
1336 lines
54 KiB
Python
from rest_framework import viewsets, status
|
||
from rest_framework.decorators import action, api_view, permission_classes
|
||
from rest_framework.response import Response
|
||
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||
from rest_framework.pagination import PageNumberPagination
|
||
from django.contrib.auth.models import User
|
||
from django.db.models import Count, Q, Avg
|
||
from django.utils import timezone
|
||
from datetime import timedelta
|
||
import json
|
||
|
||
from .models import Task, Report, TaskLog
|
||
from .serializers import (
|
||
TaskSerializer, CreateTaskSerializer, TaskDetailSerializer,
|
||
ReportSerializer, ReportListSerializer, UpdateTaskStatusSerializer,
|
||
TaskStatisticsSerializer, ReportStatisticsSerializer
|
||
)
|
||
from .services import TaskService, ReportService, AITitleGenerator
|
||
|
||
class DynamicPageSizePagination(PageNumberPagination):
|
||
page_size_query_param = 'size'
|
||
page_size = 10
|
||
max_page_size = 100
|
||
|
||
class TaskViewSet(viewsets.ModelViewSet):
|
||
"""任务管理ViewSet"""
|
||
|
||
serializer_class = TaskSerializer
|
||
pagination_class = DynamicPageSizePagination
|
||
# permission_classes = [IsAuthenticated] # 暂时注释掉,方便测试
|
||
|
||
def get_queryset(self):
|
||
"""获取当前用户的任务列表"""
|
||
# 暂时返回所有任务,实际应该过滤用户
|
||
return Task.objects.all()
|
||
|
||
def get_serializer_class(self):
|
||
"""根据action选择序列化器"""
|
||
if self.action == 'create':
|
||
return CreateTaskSerializer
|
||
elif self.action == 'retrieve':
|
||
return TaskDetailSerializer
|
||
elif self.action == 'update_status':
|
||
return UpdateTaskStatusSerializer
|
||
return TaskSerializer
|
||
|
||
def create(self, request):
|
||
"""创建任务"""
|
||
serializer = self.get_serializer(data=request.data)
|
||
serializer.is_valid(raise_exception=True)
|
||
|
||
# 暂时使用第一个用户,实际应该使用request.user
|
||
user = User.objects.first()
|
||
if not user:
|
||
# 创建默认用户用于测试
|
||
user = User.objects.create_user(
|
||
username='testuser',
|
||
email='test@example.com',
|
||
password='testpass123'
|
||
)
|
||
|
||
# 使用服务层创建任务
|
||
task = TaskService.create_task(user, serializer.validated_data)
|
||
|
||
# 返回创建结果
|
||
return Response({
|
||
'code': 200,
|
||
'message': '任务创建成功',
|
||
'data': {
|
||
'taskId': task.id,
|
||
'title': task.title,
|
||
'description': task.description,
|
||
'status': task.status
|
||
},
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
}, status=status.HTTP_201_CREATED)
|
||
|
||
def list(self, request):
|
||
"""获取任务列表"""
|
||
queryset = self.get_queryset()
|
||
|
||
# 筛选参数
|
||
task_status = request.query_params.get('status')
|
||
if task_status:
|
||
queryset = queryset.filter(status=task_status)
|
||
|
||
# 排序(有新报告的任务排在前面)
|
||
sort_by = request.query_params.get('sortBy', 'lastReportTime')
|
||
sort_order = request.query_params.get('sortOrder', 'desc')
|
||
|
||
if sort_by == 'lastReportTime':
|
||
if sort_order == 'desc':
|
||
queryset = queryset.order_by('-last_report_time', '-created_at')
|
||
else:
|
||
queryset = queryset.order_by('last_report_time', 'created_at')
|
||
elif sort_by == 'createdAt':
|
||
if sort_order == 'desc':
|
||
queryset = queryset.order_by('-created_at')
|
||
else:
|
||
queryset = queryset.order_by('created_at')
|
||
|
||
# 分页
|
||
page = self.paginate_queryset(queryset)
|
||
if page is not None:
|
||
serializer = self.get_serializer(page, many=True)
|
||
result = self.get_paginated_response(serializer.data)
|
||
|
||
# 转换为标准响应格式
|
||
return Response({
|
||
'code': 200,
|
||
'data': {
|
||
'tasks': result.data['results'],
|
||
'total': result.data['count'],
|
||
'page': int(request.query_params.get('page', 1)),
|
||
'size': int(request.query_params.get('size', 10)),
|
||
'totalPages': (result.data['count'] + int(request.query_params.get('size', 10)) - 1) // int(request.query_params.get('size', 10))
|
||
},
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
})
|
||
|
||
serializer = self.get_serializer(queryset, many=True)
|
||
return Response({
|
||
'code': 200,
|
||
'data': {
|
||
'tasks': serializer.data,
|
||
'total': len(serializer.data),
|
||
'page': 1,
|
||
'size': len(serializer.data),
|
||
'totalPages': 1
|
||
},
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
})
|
||
|
||
def retrieve(self, request, pk=None):
|
||
"""获取单个任务详情"""
|
||
try:
|
||
task = self.get_object()
|
||
serializer = TaskDetailSerializer(task)
|
||
return Response({
|
||
'code': 200,
|
||
'data': serializer.data,
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
})
|
||
except Task.DoesNotExist:
|
||
return Response({
|
||
'code': 404,
|
||
'message': '任务不存在',
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
}, status=status.HTTP_404_NOT_FOUND)
|
||
|
||
def update(self, request, pk=None):
|
||
"""更新任务"""
|
||
try:
|
||
task = self.get_object()
|
||
|
||
# 使用CreateTaskSerializer进行验证
|
||
serializer = CreateTaskSerializer(data=request.data)
|
||
if serializer.is_valid():
|
||
# 更新任务基本信息
|
||
task.requirement = serializer.validated_data.get('requirement', task.requirement)
|
||
task.type = serializer.validated_data.get('type', task.type)
|
||
task.schedule_config = serializer.validated_data.get('schedule', task.schedule_config)
|
||
task.web_search_enabled = serializer.validated_data.get('webSearchEnabled', task.web_search_enabled)
|
||
|
||
# 重新生成AI标题和描述(如果需求发生变化)
|
||
if 'requirement' in request.data:
|
||
ai_generator = AITitleGenerator()
|
||
title, description = ai_generator.generate_title_and_description(task.requirement)
|
||
task.title = title
|
||
task.description = description
|
||
|
||
task.updated_at = timezone.now()
|
||
task.save()
|
||
|
||
# 记录日志
|
||
from .models import TaskLog
|
||
TaskLog.objects.create(
|
||
task=task,
|
||
action_type='updated',
|
||
message=f'任务已更新:{task.title}'
|
||
)
|
||
|
||
return Response({
|
||
'code': 200,
|
||
'message': '任务更新成功',
|
||
'data': {
|
||
'taskId': task.id,
|
||
'title': task.title,
|
||
'description': task.description,
|
||
'status': task.status
|
||
},
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
})
|
||
else:
|
||
return Response({
|
||
'code': 400,
|
||
'message': '请求参数错误',
|
||
'errors': serializer.errors,
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
}, status=status.HTTP_400_BAD_REQUEST)
|
||
|
||
except Task.DoesNotExist:
|
||
return Response({
|
||
'code': 404,
|
||
'message': '任务不存在',
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
}, status=status.HTTP_404_NOT_FOUND)
|
||
|
||
def destroy(self, request, pk=None):
|
||
"""删除任务"""
|
||
try:
|
||
task = self.get_object()
|
||
task_title = task.title
|
||
task_id = task.id
|
||
|
||
# 记录删除日志
|
||
from .models import TaskLog
|
||
TaskLog.objects.create(
|
||
task=task,
|
||
action_type='deleted',
|
||
message=f'任务已删除:{task_title}'
|
||
)
|
||
|
||
# 删除任务(相关的报告和日志会通过外键级联删除)
|
||
task.delete()
|
||
|
||
return Response({
|
||
'code': 200,
|
||
'message': '任务删除成功',
|
||
'data': {
|
||
'taskId': task_id,
|
||
'title': task_title
|
||
},
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
})
|
||
|
||
except Task.DoesNotExist:
|
||
return Response({
|
||
'code': 404,
|
||
'message': '任务不存在',
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
}, status=status.HTTP_404_NOT_FOUND)
|
||
|
||
@action(detail=True, methods=['post'])
|
||
def execute(self, request, pk=None):
|
||
"""执行一次任务"""
|
||
try:
|
||
task = self.get_object()
|
||
|
||
# 调用任务服务执行任务
|
||
task_service = TaskService()
|
||
result = task_service.start_task_execution(task.id)
|
||
|
||
return Response({
|
||
'code': 200,
|
||
'message': '任务开始执行',
|
||
'data': {
|
||
'taskId': task.id,
|
||
'title': task.title,
|
||
'status': task.status
|
||
},
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
})
|
||
|
||
except Task.DoesNotExist:
|
||
return Response({
|
||
'code': 404,
|
||
'message': '任务不存在',
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
}, status=status.HTTP_404_NOT_FOUND)
|
||
|
||
@action(detail=True, methods=['post'])
|
||
def pause(self, request, pk=None):
|
||
"""暂停任务"""
|
||
try:
|
||
task = self.get_object()
|
||
|
||
# 调用任务服务暂停任务
|
||
task_service = TaskService()
|
||
result = task_service.pause_task(task.id)
|
||
|
||
return Response({
|
||
'code': 200,
|
||
'message': '任务已暂停',
|
||
'data': {
|
||
'taskId': task.id,
|
||
'title': task.title,
|
||
'status': task.status
|
||
},
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
})
|
||
|
||
except Task.DoesNotExist:
|
||
return Response({
|
||
'code': 404,
|
||
'message': '任务不存在',
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
}, status=status.HTTP_404_NOT_FOUND)
|
||
|
||
@action(detail=True, methods=['post'])
|
||
def resume(self, request, pk=None):
|
||
"""恢复任务"""
|
||
try:
|
||
task = self.get_object()
|
||
|
||
# 调用任务服务恢复任务
|
||
task_service = TaskService()
|
||
result = task_service.resume_task(task.id)
|
||
|
||
return Response({
|
||
'code': 200,
|
||
'message': '任务已恢复',
|
||
'data': {
|
||
'taskId': task.id,
|
||
'title': task.title,
|
||
'status': task.status
|
||
},
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
})
|
||
|
||
except Task.DoesNotExist:
|
||
return Response({
|
||
'code': 404,
|
||
'message': '任务不存在',
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
}, status=status.HTTP_404_NOT_FOUND)
|
||
|
||
@action(detail=True, methods=['post'])
|
||
def execute(self, request, pk=None):
|
||
"""执行一次任务"""
|
||
try:
|
||
task = self.get_object()
|
||
|
||
# 获取请求数据
|
||
requirement = request.data.get('requirement', task.requirement)
|
||
sources_config = request.data.get('sources_config', task.sources_config)
|
||
web_search_enabled = request.data.get('web_search_enabled', task.web_search_enabled)
|
||
|
||
# 🔥 在控制台打印接收到的前端数据
|
||
print('=' * 80)
|
||
print('📥 后端接收到的前端数据:')
|
||
print('=' * 80)
|
||
print(f'• task_id: {task.id}')
|
||
print(f'• requirement: {requirement}')
|
||
print(f'• task_type: {task.type}')
|
||
print(f'• sources_config: {sources_config}')
|
||
print(f'• web_search_enabled: {web_search_enabled}')
|
||
print('=' * 80)
|
||
|
||
# 🚀 第一步:向刘老师发送爬虫请求
|
||
from django.utils import timezone
|
||
from datetime import datetime
|
||
|
||
# 获取当前执行时间戳
|
||
current_timestamp = timezone.now()
|
||
|
||
# 获取上次执行时间戳(用于增量爬取)
|
||
last_execution_time = task.last_report_time or task.created_at
|
||
|
||
# 准备发送给刘老师的爬虫请求数据
|
||
crawler_request_data = {
|
||
'task_id': task.id,
|
||
'sources_config': sources_config,
|
||
'current_execution_time': current_timestamp.isoformat(),
|
||
'last_execution_time': last_execution_time.isoformat(),
|
||
'web_search_enabled': web_search_enabled,
|
||
'requirement': requirement # 可能影响爬取策略
|
||
}
|
||
|
||
print('=' * 80)
|
||
print('🕷️ 第一步:向刘老师发送爬虫请求')
|
||
print('📤 爬虫请求API:http://liu-teacher-api/crawl-data')
|
||
print('📋 请求数据:')
|
||
import json
|
||
print(json.dumps(crawler_request_data, ensure_ascii=False, indent=2))
|
||
print('=' * 80)
|
||
|
||
# 直接生成数据源内容(跳过刘老师爬虫模拟)
|
||
print('📊 准备数据源内容...')
|
||
source_contents = []
|
||
|
||
# 如果没有数据源配置,添加一些默认的测试数据源
|
||
if not sources_config or not sources_config.get('presetSources'):
|
||
print('⚠️ 没有数据源配置,使用默认测试数据源')
|
||
sources_config = {
|
||
'presetSources': [
|
||
{
|
||
'id': 'test-wechat-1',
|
||
'name': '测试微信群',
|
||
'category': 'wechat',
|
||
'type': '微信|企微'
|
||
},
|
||
{
|
||
'id': 'test-web-1',
|
||
'name': '测试网页',
|
||
'category': 'web',
|
||
'type': '网页'
|
||
}
|
||
],
|
||
'webSearchEnabled': True
|
||
}
|
||
|
||
if sources_config and sources_config.get('presetSources'):
|
||
for source in sources_config['presetSources']:
|
||
# TODO: 这里应该调用刘老师的数据库API获取实际的长文本内容
|
||
# content = get_source_content_from_database(source['id'])
|
||
|
||
# 🔥 打印每个数据源的详细信息
|
||
print(f'📋 处理数据源: {source}')
|
||
print(f'📋 数据源类型: {type(source)}')
|
||
print(f'📋 数据源keys: {list(source.keys()) if isinstance(source, dict) else "不是字典"}')
|
||
|
||
# 现在使用写死的模拟数据
|
||
source_category = source.get('category', 'unknown')
|
||
print(f'📋 数据源分类: {source_category}')
|
||
|
||
if source_category == 'wechat':
|
||
content = f"""
|
||
# 微信企微群聊记录 - {source['name']}
|
||
|
||
[2025-09-19 09:00] 张三: 大家好,今天我们来讨论一下AI技术的最新发展
|
||
[2025-09-19 09:02] 李四: OpenAI最近发布了新的GPT模型,性能提升很大
|
||
[2025-09-19 09:05] 王五: 是的,我看到他们在多模态方面有重大突破
|
||
[2025-09-19 09:10] 张三: 这对我们的产品开发有什么启发吗?
|
||
[2025-09-19 09:15] 李四: 我觉得可以考虑集成更多的AI功能到我们的系统中
|
||
[2025-09-19 09:20] 王五: 同意,特别是在自然语言处理方面
|
||
...(更多聊天记录,实际会有几千字的内容)
|
||
""".strip()
|
||
elif source_category == 'wechatOfficial':
|
||
content = f"""
|
||
# {source['name']} - 公众号文章内容
|
||
|
||
## 标题:AI技术发展趋势分析
|
||
|
||
随着人工智能技术的快速发展,我们看到了许多令人兴奋的突破。从GPT-4的发布到多模态AI的兴起,整个行业都在经历着前所未有的变革。
|
||
|
||
### 主要发展方向
|
||
|
||
1. **大语言模型的进化**
|
||
- 模型规模持续增长
|
||
- 推理能力显著提升
|
||
- 多语言支持更加完善
|
||
|
||
2. **多模态AI的突破**
|
||
- 文本、图像、音频的统一处理
|
||
- 跨模态理解能力增强
|
||
- 应用场景大幅扩展
|
||
|
||
3. **AI应用的普及**
|
||
- 企业级应用快速增长
|
||
- 个人AI助手成为标配
|
||
- 行业解决方案日趋成熟
|
||
|
||
### 未来展望
|
||
|
||
人工智能技术将继续深度融入各行各业,为社会带来更大的价值...
|
||
(实际会有几千字的完整文章内容)
|
||
""".strip()
|
||
elif source_category == 'web':
|
||
content = f"""
|
||
# {source['name']} - 网页内容
|
||
|
||
## OpenAI官方发布:GPT-4 Turbo正式上线
|
||
|
||
发布时间:2025年9月19日
|
||
|
||
### 主要更新内容
|
||
|
||
OpenAI今天宣布GPT-4 Turbo正式向所有用户开放,这是继GPT-4之后的又一重大更新。新版本在以下方面有显著改进:
|
||
|
||
#### 性能提升
|
||
- 推理速度提升40%
|
||
- 上下文长度扩展到128K tokens
|
||
- 成本降低50%
|
||
|
||
#### 新功能特性
|
||
- 增强的代码理解能力
|
||
- 改进的多语言支持
|
||
- 更准确的事实性回答
|
||
- 优化的创意写作能力
|
||
|
||
### 技术细节
|
||
|
||
GPT-4 Turbo采用了全新的架构设计,通过优化注意力机制和参数分布,实现了更高的效率和更好的性能...
|
||
(实际会有几千字的完整网页内容)
|
||
""".strip()
|
||
else:
|
||
content = f"""
|
||
# {source['name']} - 数据源内容
|
||
|
||
这是来自{source_category}类型数据源的模拟长文本内容。
|
||
|
||
## 内容概述
|
||
|
||
{source['name']}是一个重要的信息来源,包含了丰富的相关信息和数据。通过分析这些内容,我们可以获得有价值的洞察和趋势信息。
|
||
|
||
## 详细内容
|
||
|
||
(这里是详细的文本内容,实际使用时会从刘老师的数据库中获取真实的长文本数据)
|
||
|
||
内容长度通常在几千到几万字之间,包含了从各种数据源收集到的完整信息...
|
||
""".strip()
|
||
|
||
source_contents.append({
|
||
'source_id': source['id'],
|
||
'source_name': source['name'],
|
||
'source_type': source['category'],
|
||
'content': content
|
||
})
|
||
|
||
# 🚀 第二步:向王璞发送报告生成请求
|
||
report_generation_data = {
|
||
'task_id': task.id,
|
||
'requirement': requirement,
|
||
'source_contents': source_contents, # 修改字段名以匹配王璞接口
|
||
'web_search_enabled': web_search_enabled
|
||
}
|
||
|
||
print('=' * 80)
|
||
print('🤖 第二步:向王璞发送报告生成请求')
|
||
print('📤 报告生成API:http://47.83.141.164:7788/generate_report')
|
||
print('📋 请求数据:')
|
||
print(json.dumps(report_generation_data, ensure_ascii=False, indent=2))
|
||
print('=' * 80)
|
||
|
||
# 🎯 调用王璞的真实情报分析接口
|
||
print('🎯 开始调用王璞的真实情报分析接口...')
|
||
|
||
try:
|
||
import requests
|
||
|
||
# 调用王璞的接口
|
||
response = requests.post(
|
||
'http://47.83.141.164:7788/generate_report',
|
||
json=report_generation_data,
|
||
headers={'Content-Type': 'application/json'},
|
||
timeout=600 # 10分钟超时
|
||
)
|
||
|
||
if response.status_code == 200:
|
||
wangpu_result = response.json()
|
||
print('✅ 王璞接口调用成功!')
|
||
print('📊 返回数据:')
|
||
print(json.dumps(wangpu_result, ensure_ascii=False, indent=2))
|
||
|
||
# 从王璞的返回结果中提取报告内容
|
||
final_report = wangpu_result.get('final_report', '')
|
||
|
||
if final_report:
|
||
# 保存报告到数据库
|
||
from .models import Report
|
||
|
||
report = Report.objects.create(
|
||
task=task,
|
||
title=f"智能分析报告 - {timezone.now().strftime('%Y.%m.%d %H:%M')}",
|
||
summary=final_report[:200] + '...' if len(final_report) > 200 else final_report,
|
||
content=final_report,
|
||
status='completed',
|
||
word_count=len(final_report)
|
||
)
|
||
|
||
print(f'✅ 报告已保存到数据库,ID: {report.id}')
|
||
|
||
# 更新任务状态和最后报告时间
|
||
task.status = 'running'
|
||
task.last_report_time = timezone.now()
|
||
task.save()
|
||
|
||
return Response({
|
||
'code': 200,
|
||
'message': '任务执行成功,报告已生成',
|
||
'data': {
|
||
'taskId': task.id,
|
||
'reportId': report.id,
|
||
'title': report.title,
|
||
'summary': report.summary,
|
||
'generated_time': report.generated_at.isoformat()
|
||
},
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
})
|
||
else:
|
||
print('⚠️ 王璞接口返回的报告内容为空')
|
||
raise Exception('报告内容为空')
|
||
|
||
else:
|
||
print(f'❌ 王璞接口调用失败,状态码: {response.status_code}')
|
||
print(f'❌ 响应内容: {response.text}')
|
||
raise Exception(f'王璞接口调用失败: {response.status_code}')
|
||
|
||
except Exception as e:
|
||
print(f'❌ 调用王璞接口失败: {str(e)}')
|
||
print('🔄 回退到本地生成报告...')
|
||
|
||
# 如果王璞接口失败,回退到本地生成
|
||
# 🎭 自导自演:直接生成报告(跳过王璞API模拟)
|
||
print('🎬 开始自导自演:直接生成报告...')
|
||
|
||
# 🎭 生成真实的模拟报告内容
|
||
import random
|
||
|
||
# 根据需求生成不同的报告内容
|
||
if "AI" in requirement or "人工智能" in requirement:
|
||
report_title = f"AI技术发展深度分析报告 - {timezone.now().strftime('%Y.%m.%d')}"
|
||
ai_trends = [
|
||
"大语言模型性能持续突破,GPT-4等模型在多项基准测试中刷新记录",
|
||
"多模态AI技术快速发展,图像、语音、文本融合处理能力显著提升",
|
||
"AI芯片算力需求激增,英伟达、AMD等厂商推出新一代AI专用芯片",
|
||
"AI应用场景不断扩展,从科研到商业应用全面开花",
|
||
"开源AI生态日趋完善,Hugging Face等平台汇聚大量开发者"
|
||
]
|
||
market_insights = [
|
||
"全球AI投资规模预计2025年将达到2000亿美元",
|
||
"中国AI企业融资活跃,独角兽企业数量持续增长",
|
||
"AI人才需求激增,相关岗位薪资水平显著提升",
|
||
"传统行业AI转型加速,制造业、金融业应用最为积极"
|
||
]
|
||
recommendations = [
|
||
"关注大模型技术发展,及时跟进最新研究成果",
|
||
"加强AI人才培养,建立专业团队",
|
||
"探索AI在具体业务场景中的应用价值",
|
||
"建立AI伦理规范,确保技术应用的安全性和合规性"
|
||
]
|
||
|
||
elif "技术" in requirement or "科技" in requirement:
|
||
report_title = f"前沿技术发展报告 - {timezone.now().strftime('%Y.%m.%d')}"
|
||
ai_trends = [
|
||
"量子计算技术取得重要突破,IBM、谷歌等公司发布新一代量子处理器",
|
||
"5G/6G网络建设加速,边缘计算与云计算深度融合",
|
||
"区块链技术向Web3.0演进,去中心化应用生态日趋成熟",
|
||
"新能源技术快速发展,储能、光伏、风电成本持续下降",
|
||
"生物技术领域创新活跃,基因编辑、合成生物学应用前景广阔"
|
||
]
|
||
market_insights = [
|
||
"全球科技投资重点转向硬科技和基础研究",
|
||
"各国政府加大科技投入,制定长期发展战略",
|
||
"科技巨头持续加大研发投入,创新竞争日趋激烈",
|
||
"新兴科技企业快速成长,独角兽企业数量创新高"
|
||
]
|
||
recommendations = [
|
||
"紧跟前沿技术发展趋势,及时调整技术路线",
|
||
"加强产学研合作,提升技术创新能力",
|
||
"关注政策导向,把握发展机遇",
|
||
"建立技术评估体系,科学决策技术投入"
|
||
]
|
||
|
||
else:
|
||
report_title = f"智能信息分析报告 - {timezone.now().strftime('%Y.%m.%d')}"
|
||
ai_trends = [
|
||
"信息获取方式多样化,社交媒体、专业平台、学术资源并重",
|
||
"数据质量成为关键因素,结构化数据价值凸显",
|
||
"实时信息处理需求增长,时效性要求不断提高",
|
||
"跨平台信息整合能力成为核心竞争力",
|
||
"信息安全和隐私保护要求日益严格"
|
||
]
|
||
market_insights = [
|
||
"信息服务业快速发展,市场规模持续扩大",
|
||
"企业数字化转型加速,信息需求激增",
|
||
"个人用户信息消费习惯改变,移动端占比提升",
|
||
"信息质量评估和筛选工具需求增长"
|
||
]
|
||
recommendations = [
|
||
"建立多渠道信息收集体系,提升信息获取效率",
|
||
"加强信息质量评估,确保数据准确性",
|
||
"关注信息安全,建立完善的数据保护机制",
|
||
"持续优化信息处理流程,提升用户体验"
|
||
]
|
||
|
||
# 随机选择内容
|
||
selected_trends = random.sample(ai_trends, min(3, len(ai_trends)))
|
||
selected_insights = random.sample(market_insights, min(2, len(market_insights)))
|
||
selected_recommendations = random.sample(recommendations, min(3, len(recommendations)))
|
||
|
||
# 生成数据统计
|
||
total_sources = len(source_contents)
|
||
total_content_length = sum(len(s.get('content', '')) for s in source_contents)
|
||
web_search_status = "启用" if web_search_enabled else "禁用"
|
||
|
||
# 生成报告内容
|
||
report_content = f"""
|
||
# {report_title}
|
||
|
||
## 📊 执行摘要
|
||
根据您的需求**"{requirement}"**,我们通过智能信息采集系统分析了以下数据源:
|
||
|
||
- **数据源数量**: {total_sources} 个
|
||
- **总文本长度**: {total_content_length:,} 字符
|
||
- **联网搜索**: {web_search_status}
|
||
- **分析时间**: {timezone.now().strftime('%Y年%m月%d日 %H:%M')}
|
||
|
||
## 🔍 主要发现
|
||
|
||
### 技术发展趋势
|
||
{chr(10).join([f"{i+1}. {trend}" for i, trend in enumerate(selected_trends)])}
|
||
|
||
### 市场动态分析
|
||
{chr(10).join([f"- {insight}" for insight in selected_insights])}
|
||
|
||
## 📈 深度分析
|
||
|
||
### 技术层面
|
||
基于收集的数据分析,当前技术发展呈现出以下特点:
|
||
|
||
- **创新速度加快**: 技术迭代周期缩短,新产品、新应用层出不穷
|
||
- **跨领域融合**: 不同技术领域之间的融合趋势明显,产生新的应用场景
|
||
- **开源生态**: 开源技术社区活跃,推动技术快速普及和应用
|
||
- **标准化进程**: 行业标准逐步建立,为技术应用提供规范指导
|
||
|
||
### 应用层面
|
||
从实际应用角度来看:
|
||
|
||
- **企业应用**: 大型企业积极布局,中小企业逐步跟进
|
||
- **个人用户**: 用户接受度不断提高,使用习惯逐步养成
|
||
- **政府支持**: 政策环境持续优化,为技术发展提供有力支撑
|
||
- **国际合作**: 跨国合作增多,技术交流更加频繁
|
||
|
||
## 💡 建议与展望
|
||
|
||
基于以上分析,我们建议:
|
||
|
||
{chr(10).join([f"{i+1}. {rec}" for i, rec in enumerate(selected_recommendations)])}
|
||
|
||
### 未来展望
|
||
- 技术发展将更加注重实用性和可持续性
|
||
- 人工智能与传统行业的融合将更加深入
|
||
- 数据安全和隐私保护将成为重要考量因素
|
||
- 国际合作将在技术发展中发挥更大作用
|
||
|
||
---
|
||
**报告生成时间**: {timezone.now().strftime('%Y年%m月%d日 %H:%M:%S')}
|
||
**数据来源**: 智能信息采集系统
|
||
**分析引擎**: AI智能分析平台 v2.0
|
||
""".strip()
|
||
|
||
report_summary = f"基于{len(source_contents)}个数据源的分析报告,涵盖{requirement[:30]}..."
|
||
|
||
# 直接创建报告
|
||
from .models import Report, TaskLog
|
||
|
||
report = Report.objects.create(
|
||
task=task,
|
||
title=report_title,
|
||
content=report_content,
|
||
summary=report_summary,
|
||
status='completed',
|
||
generated_at=timezone.now()
|
||
)
|
||
|
||
# 更新任务状态
|
||
task.status = 'running'
|
||
task.last_report_time = timezone.now()
|
||
task.save()
|
||
|
||
# 记录日志
|
||
TaskLog.objects.create(
|
||
task=task,
|
||
action_type='completed',
|
||
message=f'报告生成完成: {report.title}'
|
||
)
|
||
|
||
print(f'✅ 自导自演完成:报告已保存 - {report.title}')
|
||
print(f'📊 任务状态更新: {task.title} -> {task.status}')
|
||
print('=' * 80)
|
||
|
||
# 更新任务状态为生成中
|
||
task.status = 'generating'
|
||
task.save()
|
||
|
||
return Response({
|
||
'code': 200,
|
||
'message': '任务已开始执行,正在生成报告',
|
||
'data': {
|
||
'taskId': task.id,
|
||
'title': task.title,
|
||
'status': task.status,
|
||
'report_generation_data': report_generation_data
|
||
},
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
})
|
||
|
||
except Task.DoesNotExist:
|
||
return Response({
|
||
'code': 404,
|
||
'message': '任务不存在',
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
}, status=status.HTTP_404_NOT_FOUND)
|
||
|
||
@action(detail=True, methods=['post'], url_path='reports')
|
||
def create_report(self, request, pk=None):
|
||
"""接收其他团队生成的报告"""
|
||
try:
|
||
task = self.get_object()
|
||
|
||
# 验证请求数据
|
||
required_fields = ['title', 'summary', 'content', 'source_tag']
|
||
for field in required_fields:
|
||
if field not in request.data:
|
||
return Response({
|
||
'code': 400,
|
||
'message': f'缺少必填字段: {field}',
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
}, status=status.HTTP_400_BAD_REQUEST)
|
||
|
||
# 创建报告
|
||
from .models import Report, ReportSource
|
||
report = Report.objects.create(
|
||
task=task,
|
||
title=request.data['title'],
|
||
summary=request.data['summary'],
|
||
content=request.data['content'],
|
||
source_tag=request.data['source_tag'],
|
||
status='completed'
|
||
)
|
||
|
||
# 创建报告来源记录
|
||
if 'sources' in request.data:
|
||
for source_data in request.data['sources']:
|
||
ReportSource.objects.create(
|
||
report=report,
|
||
source_type=source_data.get('source_type', 'unknown'),
|
||
source_name=source_data.get('source_name', ''),
|
||
source_url=source_data.get('source_url', ''),
|
||
data_content=source_data.get('data_content', '')
|
||
)
|
||
|
||
# 更新任务状态
|
||
task.last_report_time = timezone.now()
|
||
task.status = 'running' # 报告生成完成后恢复运行状态
|
||
task.save()
|
||
|
||
# 记录日志
|
||
from .models import TaskLog
|
||
TaskLog.objects.create(
|
||
task=task,
|
||
action_type='report_generated',
|
||
message=f'生成报告:{report.title}'
|
||
)
|
||
|
||
return Response({
|
||
'code': 200,
|
||
'message': '报告创建成功',
|
||
'data': {
|
||
'reportId': report.id,
|
||
'taskId': task.id,
|
||
'title': report.title,
|
||
'summary': report.summary
|
||
},
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
})
|
||
|
||
except Task.DoesNotExist:
|
||
return Response({
|
||
'code': 404,
|
||
'message': '任务不存在',
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
}, status=status.HTTP_404_NOT_FOUND)
|
||
except Exception as e:
|
||
return Response({
|
||
'code': 500,
|
||
'message': f'报告创建失败: {str(e)}',
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||
|
||
@action(detail=True, methods=['post'], url_path='status')
|
||
def update_status(self, request, pk=None):
|
||
"""更新任务执行状态(供其他团队调用)"""
|
||
try:
|
||
task = self.get_object()
|
||
|
||
new_status = request.data.get('status')
|
||
message = request.data.get('message', '')
|
||
error_details = request.data.get('error_details')
|
||
|
||
if new_status not in ['running', 'generating', 'paused', 'error', 'completed']:
|
||
return Response({
|
||
'code': 400,
|
||
'message': '无效的状态值',
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
}, status=status.HTTP_400_BAD_REQUEST)
|
||
|
||
# 更新任务状态
|
||
old_status = task.status
|
||
task.status = new_status
|
||
task.updated_at = timezone.now()
|
||
task.save()
|
||
|
||
# 记录状态变更日志
|
||
from .models import TaskLog
|
||
TaskLog.objects.create(
|
||
task=task,
|
||
action_type='status_updated',
|
||
message=message or f'状态从 {old_status} 变更为 {new_status}',
|
||
error_details=error_details
|
||
)
|
||
|
||
return Response({
|
||
'code': 200,
|
||
'message': '状态更新成功',
|
||
'data': {
|
||
'taskId': task.id,
|
||
'oldStatus': old_status,
|
||
'newStatus': new_status,
|
||
'updatedAt': task.updated_at.isoformat()
|
||
},
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
})
|
||
|
||
except Task.DoesNotExist:
|
||
return Response({
|
||
'code': 404,
|
||
'message': '任务不存在',
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
}, status=status.HTTP_404_NOT_FOUND)
|
||
|
||
|
||
class ReportViewSet(viewsets.ReadOnlyModelViewSet):
|
||
"""报告管理ViewSet"""
|
||
|
||
serializer_class = ReportListSerializer
|
||
|
||
def get_queryset(self):
|
||
"""获取报告列表"""
|
||
queryset = Report.objects.all()
|
||
|
||
# 可以按任务ID筛选
|
||
task_id = self.request.query_params.get('taskId')
|
||
if task_id:
|
||
queryset = queryset.filter(task_id=task_id)
|
||
|
||
return queryset.order_by('-generated_at', '-created_at')
|
||
|
||
def get_serializer_class(self):
|
||
"""根据action选择序列化器"""
|
||
if self.action == 'retrieve':
|
||
return ReportSerializer
|
||
return ReportListSerializer
|
||
|
||
|
||
class StatisticsViewSet(viewsets.ViewSet):
|
||
"""统计分析ViewSet"""
|
||
|
||
@action(detail=False, methods=['get'])
|
||
def tasks(self, request):
|
||
"""获取任务统计"""
|
||
user_tasks = Task.objects.all()
|
||
|
||
stats = {
|
||
'total_tasks': user_tasks.count(),
|
||
'running_tasks': user_tasks.filter(status='running').count(),
|
||
'paused_tasks': user_tasks.filter(status='paused').count(),
|
||
'error_tasks': user_tasks.filter(status='error').count(),
|
||
'completed_tasks': user_tasks.filter(status='completed').count(),
|
||
'today_reports': Report.objects.filter(
|
||
task__in=user_tasks,
|
||
generated_at__date=timezone.now().date()
|
||
).count(),
|
||
'weekly_reports': Report.objects.filter(
|
||
task__in=user_tasks,
|
||
generated_at__gte=timezone.now() - timedelta(days=7)
|
||
).count(),
|
||
}
|
||
|
||
return Response({
|
||
'code': 200,
|
||
'data': stats,
|
||
'timestamp': timezone.now().isoformat(),
|
||
'requestId': f'req-{timezone.now().timestamp()}'
|
||
})
|
||
|
||
|
||
@api_view(['POST'])
|
||
@permission_classes([AllowAny]) # 允许外部调用
|
||
def generate_report(request):
|
||
"""
|
||
情报生成接口
|
||
接收任务数据和数据源内容,生成智能报告
|
||
"""
|
||
try:
|
||
data = request.data
|
||
print('=' * 80)
|
||
print('📥 收到情报生成请求')
|
||
print('📋 请求数据:')
|
||
print(json.dumps(data, ensure_ascii=False, indent=2))
|
||
print('=' * 80)
|
||
|
||
# 验证必要字段
|
||
required_fields = ['task_id', 'requirement', 'source_contents']
|
||
for field in required_fields:
|
||
if field not in data:
|
||
return Response({
|
||
'code': 400,
|
||
'message': f'缺少必要字段: {field}'
|
||
}, status=400)
|
||
|
||
task_id = data['task_id']
|
||
requirement = data['requirement']
|
||
source_contents = data['source_contents']
|
||
web_search_enabled = data.get('web_search_enabled', False)
|
||
|
||
# 验证任务是否存在
|
||
try:
|
||
task = Task.objects.get(id=task_id)
|
||
except Task.DoesNotExist:
|
||
return Response({
|
||
'code': 404,
|
||
'message': f'任务不存在: {task_id}'
|
||
}, status=404)
|
||
|
||
# 生成报告
|
||
import random
|
||
|
||
# 根据需求生成不同的报告内容
|
||
if "AI" in requirement or "人工智能" in requirement:
|
||
report_title = f"AI技术发展深度分析报告 - {timezone.now().strftime('%Y.%m.%d')}"
|
||
ai_trends = [
|
||
"大语言模型性能持续突破,GPT-4等模型在多项基准测试中刷新记录",
|
||
"多模态AI技术快速发展,图像、语音、文本融合处理能力显著提升",
|
||
"AI芯片算力需求激增,英伟达、AMD等厂商推出新一代AI专用芯片",
|
||
"AI应用场景不断扩展,从科研到商业应用全面开花",
|
||
"开源AI生态日趋完善,Hugging Face等平台汇聚大量开发者"
|
||
]
|
||
market_insights = [
|
||
"全球AI投资规模预计2025年将达到2000亿美元",
|
||
"中国AI企业融资活跃,独角兽企业数量持续增长",
|
||
"AI人才需求激增,相关岗位薪资水平显著提升",
|
||
"传统行业AI转型加速,制造业、金融业应用最为积极"
|
||
]
|
||
recommendations = [
|
||
"关注大模型技术发展,及时跟进最新研究成果",
|
||
"加强AI人才培养,建立专业团队",
|
||
"探索AI在具体业务场景中的应用价值",
|
||
"建立AI伦理规范,确保技术应用的安全性和合规性"
|
||
]
|
||
|
||
elif "技术" in requirement or "科技" in requirement:
|
||
report_title = f"前沿技术发展报告 - {timezone.now().strftime('%Y.%m.%d')}"
|
||
ai_trends = [
|
||
"量子计算技术取得重要突破,IBM、谷歌等公司发布新一代量子处理器",
|
||
"5G/6G网络建设加速,边缘计算与云计算深度融合",
|
||
"区块链技术向Web3.0演进,去中心化应用生态日趋成熟",
|
||
"新能源技术快速发展,储能、光伏、风电成本持续下降",
|
||
"生物技术领域创新活跃,基因编辑、合成生物学应用前景广阔"
|
||
]
|
||
market_insights = [
|
||
"全球科技投资重点转向硬科技和基础研究",
|
||
"各国政府加大科技投入,制定长期发展战略",
|
||
"科技巨头持续加大研发投入,创新竞争日趋激烈",
|
||
"新兴科技企业快速成长,独角兽企业数量创新高"
|
||
]
|
||
recommendations = [
|
||
"紧跟前沿技术发展趋势,及时调整技术路线",
|
||
"加强产学研合作,提升技术创新能力",
|
||
"关注政策导向,把握发展机遇",
|
||
"建立技术评估体系,科学决策技术投入"
|
||
]
|
||
|
||
else:
|
||
report_title = f"智能信息分析报告 - {timezone.now().strftime('%Y.%m.%d')}"
|
||
ai_trends = [
|
||
"信息获取方式多样化,社交媒体、专业平台、学术资源并重",
|
||
"数据质量成为关键因素,结构化数据价值凸显",
|
||
"实时信息处理需求增长,时效性要求不断提高",
|
||
"跨平台信息整合能力成为核心竞争力",
|
||
"信息安全和隐私保护要求日益严格"
|
||
]
|
||
market_insights = [
|
||
"信息服务业快速发展,市场规模持续扩大",
|
||
"企业数字化转型加速,信息需求激增",
|
||
"个人用户信息消费习惯改变,移动端占比提升",
|
||
"信息质量评估和筛选工具需求增长"
|
||
]
|
||
recommendations = [
|
||
"建立多渠道信息收集体系,提升信息获取效率",
|
||
"加强信息质量评估,确保数据准确性",
|
||
"关注信息安全,建立完善的数据保护机制",
|
||
"持续优化信息处理流程,提升用户体验"
|
||
]
|
||
|
||
# 随机选择内容
|
||
selected_trends = random.sample(ai_trends, min(3, len(ai_trends)))
|
||
selected_insights = random.sample(market_insights, min(2, len(market_insights)))
|
||
selected_recommendations = random.sample(recommendations, min(3, len(recommendations)))
|
||
|
||
# 生成数据统计
|
||
total_sources = len(source_contents)
|
||
total_content_length = sum(len(s.get('content', '')) for s in source_contents)
|
||
web_search_status = "启用" if web_search_enabled else "禁用"
|
||
|
||
# 生成报告内容
|
||
report_content = f"""
|
||
# {report_title}
|
||
|
||
## 📊 执行摘要
|
||
根据您的需求**"{requirement}"**,我们通过智能信息采集系统分析了以下数据源:
|
||
|
||
- **数据源数量**: {total_sources} 个
|
||
- **总文本长度**: {total_content_length:,} 字符
|
||
- **联网搜索**: {web_search_status}
|
||
- **分析时间**: {timezone.now().strftime('%Y年%m月%d日 %H:%M')}
|
||
|
||
## 🔍 主要发现
|
||
|
||
### 技术发展趋势
|
||
{chr(10).join([f"{i+1}. {trend}" for i, trend in enumerate(selected_trends)])}
|
||
|
||
### 市场动态分析
|
||
{chr(10).join([f"- {insight}" for insight in selected_insights])}
|
||
|
||
## 📈 深度分析
|
||
|
||
### 技术层面
|
||
基于收集的数据分析,当前技术发展呈现出以下特点:
|
||
|
||
- **创新速度加快**: 技术迭代周期缩短,新产品、新应用层出不穷
|
||
- **跨领域融合**: 不同技术领域之间的融合趋势明显,产生新的应用场景
|
||
- **开源生态**: 开源技术社区活跃,推动技术快速普及和应用
|
||
- **标准化进程**: 行业标准逐步建立,为技术应用提供规范指导
|
||
|
||
### 应用层面
|
||
从实际应用角度来看:
|
||
|
||
- **企业应用**: 大型企业积极布局,中小企业逐步跟进
|
||
- **个人用户**: 用户接受度不断提高,使用习惯逐步养成
|
||
- **政府支持**: 政策环境持续优化,为技术发展提供有力支撑
|
||
- **国际合作**: 跨国合作增多,技术交流更加频繁
|
||
|
||
## 💡 建议与展望
|
||
|
||
基于以上分析,我们建议:
|
||
|
||
{chr(10).join([f"{i+1}. {rec}" for i, rec in enumerate(selected_recommendations)])}
|
||
|
||
### 未来展望
|
||
- 技术发展将更加注重实用性和可持续性
|
||
- 人工智能与传统行业的融合将更加深入
|
||
- 数据安全和隐私保护将成为重要考量因素
|
||
- 国际合作将在技术发展中发挥更大作用
|
||
|
||
---
|
||
**报告生成时间**: {timezone.now().strftime('%Y年%m月%d日 %H:%M:%S')}
|
||
**数据来源**: 智能信息采集系统
|
||
**分析引擎**: AI智能分析平台 v2.0
|
||
""".strip()
|
||
|
||
report_summary = f"基于{total_sources}个数据源的分析报告,涵盖{requirement[:30]}..."
|
||
|
||
# 创建报告
|
||
report = Report.objects.create(
|
||
task=task,
|
||
title=report_title,
|
||
content=report_content,
|
||
summary=report_summary,
|
||
status='completed',
|
||
generated_at=timezone.now()
|
||
)
|
||
|
||
# 更新任务状态
|
||
task.status = 'running'
|
||
task.last_report_time = timezone.now()
|
||
task.save()
|
||
|
||
# 记录日志
|
||
TaskLog.objects.create(
|
||
task=task,
|
||
action_type='completed',
|
||
message=f'报告生成完成: {report.title}'
|
||
)
|
||
|
||
print(f'✅ 报告生成成功: {report.title}')
|
||
print(f'📊 报告ID: {report.id}')
|
||
print('=' * 80)
|
||
|
||
return Response({
|
||
'code': 200,
|
||
'message': '报告生成成功',
|
||
'data': {
|
||
'report_id': report.id,
|
||
'task_id': task.id,
|
||
'title': report.title,
|
||
'summary': report.summary,
|
||
'content': report.content,
|
||
'generated_time': report.generated_at.isoformat()
|
||
}
|
||
})
|
||
|
||
except Exception as e:
|
||
print(f'❌ 报告生成失败: {str(e)}')
|
||
import traceback
|
||
traceback.print_exc()
|
||
return Response({
|
||
'code': 500,
|
||
'message': f'服务器内部错误: {str(e)}'
|
||
}, status=500)
|
||
|
||
|
||
@api_view(['POST'])
|
||
@permission_classes([AllowAny]) # 允许王璞团队调用
|
||
def report_callback(request):
|
||
"""
|
||
报告完成回调接口
|
||
接收王璞团队发送的报告数据并保存到数据库
|
||
"""
|
||
try:
|
||
data = request.data
|
||
print('=' * 80)
|
||
print('📥 收到王璞团队的报告回调')
|
||
print('📋 回调数据:')
|
||
print(json.dumps(data, ensure_ascii=False, indent=2))
|
||
print('=' * 80)
|
||
|
||
# 验证必要字段
|
||
required_fields = ['report_task_id', 'task_id', 'status', 'report_data']
|
||
for field in required_fields:
|
||
if field not in data:
|
||
return Response({
|
||
'code': 400,
|
||
'message': f'缺少必要字段: {field}'
|
||
}, status=400)
|
||
|
||
report_task_id = data['report_task_id']
|
||
task_id = data['task_id']
|
||
status = data['status']
|
||
report_data = data['report_data']
|
||
|
||
# 验证任务是否存在
|
||
try:
|
||
task = Task.objects.get(id=task_id)
|
||
except Task.DoesNotExist:
|
||
return Response({
|
||
'code': 404,
|
||
'message': f'任务不存在: {task_id}'
|
||
}, status=404)
|
||
|
||
# 验证报告数据字段
|
||
report_required_fields = ['title', 'content']
|
||
for field in report_required_fields:
|
||
if field not in report_data:
|
||
return Response({
|
||
'code': 400,
|
||
'message': f'报告数据缺少必要字段: {field}'
|
||
}, status=400)
|
||
|
||
# 根据状态处理
|
||
if status == 'completed':
|
||
# 创建或更新报告
|
||
report, created = Report.objects.get_or_create(
|
||
task=task,
|
||
title=report_data['title'],
|
||
defaults={
|
||
'content': report_data['content'],
|
||
'summary': report_data.get('summary', ''),
|
||
'status': 'completed',
|
||
'generated_at': timezone.now()
|
||
}
|
||
)
|
||
|
||
if not created:
|
||
# 更新现有报告
|
||
report.content = report_data['content']
|
||
report.summary = report_data.get('summary', '')
|
||
report.status = 'completed'
|
||
report.generated_at = timezone.now()
|
||
report.save()
|
||
|
||
# 更新任务状态
|
||
task.status = 'running' # 报告生成完成,任务回到运行状态
|
||
task.last_report_time = timezone.now()
|
||
task.save()
|
||
|
||
# 记录日志
|
||
TaskLog.objects.create(
|
||
task=task,
|
||
action_type='completed',
|
||
message=f'报告生成完成: {report.title}'
|
||
)
|
||
|
||
print(f'✅ 报告保存成功: {report.title}')
|
||
print(f'📊 任务状态更新: {task.title} -> {task.status}')
|
||
|
||
elif status == 'failed':
|
||
# 处理生成失败
|
||
task.status = 'error'
|
||
task.save()
|
||
|
||
# 记录错误日志
|
||
TaskLog.objects.create(
|
||
task=task,
|
||
action_type='error',
|
||
message=f'报告生成失败: {report_task_id}',
|
||
error_details={'report_task_id': report_task_id, 'error': '生成失败'}
|
||
)
|
||
|
||
print(f'❌ 报告生成失败: {task.title}')
|
||
|
||
else:
|
||
return Response({
|
||
'code': 400,
|
||
'message': f'不支持的状态: {status}'
|
||
}, status=400)
|
||
|
||
return Response({
|
||
'code': 200,
|
||
'message': '报告接收成功'
|
||
})
|
||
|
||
except Exception as e:
|
||
print(f'❌ 报告回调处理失败: {str(e)}')
|
||
return Response({
|
||
'code': 500,
|
||
'message': f'服务器内部错误: {str(e)}'
|
||
}, status=500) |