128 lines
5.4 KiB
Python
128 lines
5.4 KiB
Python
![]() |
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)}"
|