operations_project/apps/gmail/services/export_service.py
2025-05-21 11:14:08 +08:00

128 lines
5.4 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.

import os
import logging
import pandas as pd
from datetime import datetime
from django.db.models import Q, F
from django.utils import timezone
from apps.gmail.models import GmailConversation, GmailAttachment, ConversationSummary
from apps.chat.models import ChatHistory
logger = logging.getLogger(__name__)
class GmailExportService:
"""
Gmail导出服务提供将达人回复导出为Excel的功能
"""
@staticmethod
def export_replied_influencers(user, format='xlsx'):
"""
导出已回复的达人Gmail列表
Args:
user: 用户对象
format: 导出格式, 默认为xlsx
Returns:
tuple: (文件路径, 错误信息)
"""
try:
# 获取用户所有的Gmail对话
conversations = GmailConversation.objects.filter(
user=user,
is_active=True
)
if not conversations.exists():
return None, "未找到任何Gmail对话"
# 准备导出数据
export_data = []
for conversation in conversations:
# 查询达人是否有回复
chat_history = ChatHistory.objects.filter(
user=user,
conversation_id=conversation.conversation_id,
metadata__contains={"from": conversation.influencer_email}
).order_by('created_at')
# 如果达人有回复,则添加到导出列表
if chat_history.exists():
# 获取第一条回复的时间
first_reply = chat_history.first()
first_reply_time = first_reply.created_at.replace(tzinfo=None) if first_reply else None
# 获取最后一条回复的时间
last_reply = chat_history.last()
last_reply_time = last_reply.created_at.replace(tzinfo=None) if last_reply else None
# 获取回复次数
reply_count = chat_history.count()
# 直接从数据库中获取对话摘要不调用外部API
summary = ""
try:
# 先从ConversationSummary模型中查找
conversation_summary = ConversationSummary.objects.filter(
conversation=conversation
).first()
if conversation_summary:
summary = conversation_summary.content
else:
# 如果没有摘要,尝试获取最新的几条消息内容
recent_messages = ChatHistory.objects.filter(
user=user,
conversation_id=conversation.conversation_id
).order_by('-created_at')[:5]
if recent_messages:
summary = "最近消息: " + " | ".join([msg.content[:100] + ("..." if len(msg.content) > 100 else "") for msg in recent_messages])
except Exception as e:
logger.error(f"获取对话摘要失败: {str(e)}")
summary = '无法获取摘要'
# 构建导出记录 - 注意移除时区信息
export_record = {
'用户邮箱': conversation.user_email,
'达人邮箱': conversation.influencer_email,
'对话标题': conversation.title,
'对话开始时间': conversation.created_at.replace(tzinfo=None),
'首次回复时间': first_reply_time,
'最近回复时间': last_reply_time,
'回复次数': reply_count,
'对话摘要': summary,
'对话ID': conversation.conversation_id
}
export_data.append(export_record)
if not export_data:
return None, "没有找到已回复的达人"
# 创建DataFrame
df = pd.DataFrame(export_data)
# 生成文件名和路径
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
file_name = f"influencer_replies_{timestamp}.{format}"
export_dir = os.path.join('media', 'exports')
os.makedirs(export_dir, exist_ok=True)
file_path = os.path.join(export_dir, file_name)
# 根据格式导出
if format == 'xlsx':
df.to_excel(file_path, index=False, engine='openpyxl')
elif format == 'csv':
df.to_csv(file_path, index=False, encoding='utf-8-sig')
else:
return None, f"不支持的导出格式: {format}"
return file_path, None
except Exception as e:
logger.error(f"导出已回复达人失败: {str(e)}")
import traceback
logger.error(traceback.format_exc())
return None, f"导出失败: {str(e)}"