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)}"