101 lines
3.1 KiB
Python
101 lines
3.1 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""
|
||
|
|
龙虾议事厅 - 工具函数
|
||
|
|
"""
|
||
|
|
|
||
|
|
from .models import Meeting, Message, Participant
|
||
|
|
from datetime import datetime
|
||
|
|
from typing import List, Dict
|
||
|
|
|
||
|
|
|
||
|
|
def generate_meeting_minutes(meeting_id: str) -> Dict:
|
||
|
|
"""
|
||
|
|
生成会议纪要
|
||
|
|
|
||
|
|
Args:
|
||
|
|
meeting_id: 会议 ID
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
会议纪要字典
|
||
|
|
"""
|
||
|
|
from django.db.models import Count
|
||
|
|
|
||
|
|
meeting = Meeting.objects.get(id=meeting_id)
|
||
|
|
messages = Message.objects.filter(meeting=meeting).select_related('sender').order_by('created_at')
|
||
|
|
participants = Participant.objects.filter(meeting=meeting, left_at__isnull=True)
|
||
|
|
|
||
|
|
# 统计消息数量
|
||
|
|
message_count = messages.count()
|
||
|
|
|
||
|
|
# 统计每个参会者的消息数
|
||
|
|
participant_stats = {}
|
||
|
|
for msg in messages:
|
||
|
|
name = msg.sender.nickname
|
||
|
|
participant_stats[name] = participant_stats.get(name, 0) + 1
|
||
|
|
|
||
|
|
# 生成摘要
|
||
|
|
if message_count == 0:
|
||
|
|
summary = "本次会议暂无消息记录。"
|
||
|
|
else:
|
||
|
|
# 提取第一条和最后一条消息
|
||
|
|
first_msg = messages.first()
|
||
|
|
last_msg = messages.last()
|
||
|
|
|
||
|
|
summary = f"会议于 {meeting.created_at.strftime('%Y-%m-%d %H:%M')} 开始,"
|
||
|
|
summary += f"共 {message_count} 条消息,{participants.count()} 位参会者。"
|
||
|
|
|
||
|
|
if message_count > 0:
|
||
|
|
summary += f" 第一条消息:\"{first_msg.content[:50]}...\""
|
||
|
|
summary += f" 最后一条消息:\"{last_msg.content[:50]}...\""
|
||
|
|
|
||
|
|
# 生成待办事项(标记为需要回复的消息)
|
||
|
|
todos = messages.filter(requires_response=True).values_list('content', flat=True)
|
||
|
|
|
||
|
|
return {
|
||
|
|
'meeting_id': meeting.id,
|
||
|
|
'topic': meeting.topic,
|
||
|
|
'status': meeting.status,
|
||
|
|
'created_at': meeting.created_at.isoformat(),
|
||
|
|
'duration_minutes': None, # 会议结束前无法计算
|
||
|
|
'participant_count': participants.count(),
|
||
|
|
'message_count': message_count,
|
||
|
|
'summary': summary,
|
||
|
|
'participant_stats': participant_stats,
|
||
|
|
'todos': list(todos),
|
||
|
|
'generated_at': datetime.now().isoformat()
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
def export_minutes_to_markdown(minutes: Dict) -> str:
|
||
|
|
"""
|
||
|
|
将会话纪要导出为 Markdown 格式
|
||
|
|
|
||
|
|
Args:
|
||
|
|
minutes: generate_meeting_minutes 返回的字典
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Markdown 格式的会议纪要
|
||
|
|
"""
|
||
|
|
md = f"# 📋 会议纪要\n\n"
|
||
|
|
md += f"**主题:** {minutes['topic']}\n\n"
|
||
|
|
md += f"**时间:** {minutes['created_at']}\n\n"
|
||
|
|
md += f"**状态:** {minutes['status']}\n\n"
|
||
|
|
md += f"**参会人数:** {minutes['participant_count']}\n\n"
|
||
|
|
md += f"**消息总数:** {minutes['message_count']}\n\n"
|
||
|
|
|
||
|
|
md += "## 📊 统计\n\n"
|
||
|
|
for name, count in minutes['participant_stats'].items():
|
||
|
|
md += f"- {name}: {count} 条消息\n"
|
||
|
|
|
||
|
|
md += "\n## 📝 摘要\n\n"
|
||
|
|
md += f"{minutes['summary']}\n\n"
|
||
|
|
|
||
|
|
if minutes['todos']:
|
||
|
|
md += "## ✅ 待办事项\n\n"
|
||
|
|
for todo in minutes['todos']:
|
||
|
|
md += f"- [ ] {todo}\n"
|
||
|
|
|
||
|
|
md += f"\n---\n*生成时间:{minutes['generated_at']}*\n"
|
||
|
|
|
||
|
|
return md
|