#!/usr/bin/env python3"""每周规划生成器用于自动生成下周的任务规划并发送提醒"""import jsonimport osfrom datetime import datetime, timedeltaimport smtplibfrom email.mime.text import MIMETextfrom email.header import Headerfrom pathlib import Pathimport argparse# 配置文件路径CONFIG_FILE = "weekly_planner_config.json"TASKS_FILE = "tasks.json"TEMPLATE_FILE = "weekly_template.md"OUTPUT_DIR = "weekly_reports"class WeeklyPlanner: def __init__(self): self.config = self.load_config() self.tasks = self.load_tasks() def load_config(self): """加载配置文件""" default_config = { "email": { "enabled": False, "smtp_server": "smtp.gmail.com", "smtp_port": 587, "username": "your_email@gmail.com", "password": "your_password", "sender": "your_email@gmail.com", "receiver": "your_email@gmail.com" }, "tasks_file": "tasks.json", "output_dir": "weekly_reports", "planning_day": "Sunday", # 每周几生成规划 "planning_time": "20:00", # 生成规划的时间 "categories": [ "学习成长", "工作项目", "健康生活", "人际关系", "兴趣爱好" ] } try: with open(CONFIG_FILE, 'r', encoding='utf-8') as f: config = json.load(f) # 合并配置,确保所有必需字段都存在 for key in default_config: if key not in config: config[key] = default_config[key] return config except FileNotFoundError: print(f"配置文件不存在,创建默认配置...") # 保存默认配置 with open(CONFIG_FILE, 'w', encoding='utf-8') as f: json.dump(default_config, f, ensure_ascii=False, indent=2) return default_config def load_tasks(self): """加载任务数据""" try: with open(self.config["tasks_file"], 'r', encoding='utf-8') as f: tasks = json.load(f) return tasks except FileNotFoundError: print(f"任务文件不存在,创建示例任务文件...") sample_tasks = self.create_sample_tasks() self.save_tasks(sample_tasks) return sample_tasks def create_sample_tasks(self): """创建示例任务""" return { "tasks": [ { "id": 1, "name": "AI模型训练项目", "category": "学习成长", "estimated_hours": 2, "priority": "high", "recurring": True, "recurring_days": ["Monday", "Wednesday", "Friday"], "status": "pending", "tags": ["AI", "Python", "机器学习"] }, { "id": 2, "name": "技术博客写作", "category": "学习成长", "estimated_hours": 1.5, "priority": "medium", "recurring": True, "recurring_days": ["Saturday"], "status": "pending", "tags": ["写作", "技术分享"] }, { "id": 3, "name": "健身房锻炼", "category": "健康生活", "estimated_hours": 1, "priority": "high", "recurring": True, "recurring_days": ["Monday", "Wednesday", "Friday"], "status": "pending", "tags": ["健身", "健康"] } ] } def save_tasks(self, tasks): """保存任务数据""" with open(self.config["tasks_file"], 'w', encoding='utf-8') as f: json.dump(tasks, f, ensure_ascii=False, indent=2) def get_next_week_tasks(self): """获取下周的任务""" today = datetime.now() next_monday = today + timedelta(days=(7 - today.weekday())) next_sunday = next_monday + timedelta(days=6) week_tasks = [] for task in self.tasks["tasks"]: if task.get("recurring", False): # 检查是否是循环任务 recurring_days = task.get("recurring_days", []) for day in recurring_days: task_copy = task.copy() task_copy["scheduled_day"] = day week_tasks.append(task_copy) elif task.get("status") == "pending": # 一次性任务 week_tasks.append(task) return week_tasks, next_monday, next_sunday def generate_weekly_report(self): """生成每周规划报告""" week_tasks, next_monday, next_sunday = self.get_next_week_tasks() # 按类别分组任务 tasks_by_category = {} for category in self.config["categories"]: tasks_by_category[category] = [] for task in week_tasks: category = task.get("category", "其他") if category not in tasks_by_category: tasks_by_category[category] = [] tasks_by_category[category].append(task) # 计算总时间 total_hours = sum(task.get("estimated_hours", 0) for task in week_tasks) # 读取模板或使用默认模板 try: with open(TEMPLATE_FILE, 'r', encoding='utf-8') as f: template = f.read() except FileNotFoundError: template = """# 下周核心任务 ({start_date} - {end_date})## 📊 概览- 总任务数: {task_count} 个- 预计总耗时: {total_hours} 小时- 平均每日: {daily_hours:.1f} 小时{categories_content}## 🎯 重点关注{high_priority_content}## 💡 温馨提示1. 建议每天开始前查看当日任务2. 遇到困难时及时调整,保持灵活性3. 每周日进行复盘,优化下周计划行动,只有行动才能决定价值! 🚀""" # 生成按类别分类的内容 categories_content = "" for category, tasks in tasks_by_category.items(): if tasks: categories_content += f"\n### {category}\n" for task in tasks: emoji = "🔴" if task.get("priority") == "high" else "🟡" if task.get("priority") == "medium" else "🟢" scheduled_day = task.get("scheduled_day", "未指定") hours = task.get("estimated_hours", 0) tags = " ".join([f"`{tag}`" for tag in task.get("tags", [])]) categories_content += f"- {emoji} **{task['name']}** ({scheduled_day}, 预计{hours}小时) {tags}\n" # 生成高优先级任务内容 high_priority_tasks = [t for t in week_tasks if t.get("priority") == "high"] high_priority_content = "" if high_priority_tasks: high_priority_content = "本周有以下高优先级任务需要重点关注:\n" for task in high_priority_tasks: scheduled_day = task.get("scheduled_day", "尽快完成") high_priority_content += f"- **{task['name']}** (安排于: {scheduled_day})\n" else: high_priority_content = "本周没有高优先级任务,可以按部就班完成常规任务。" # 格式化日期 start_date_str = next_monday.strftime("%Y年%m月%d日") end_date_str = next_sunday.strftime("%Y年%m月%d日") # 渲染报告 daily_hours = total_hours / 7 if len(week_tasks) > 0 else 0 report = template.format( start_date=start_date_str, end_date=end_date_str, task_count=len(week_tasks), total_hours=total_hours, daily_hours=daily_hours, categories_content=categories_content, high_priority_content=high_priority_content ) return report, next_monday def save_report_to_file(self, report, date): """保存报告到文件""" # 创建输出目录 Path(self.config["output_dir"]).mkdir(exist_ok=True) # 生成文件名 filename = f"weekly_plan_{date.strftime('%Y%m%d')}.md" filepath = os.path.join(self.config["output_dir"], filename) with open(filepath, 'w', encoding='utf-8') as f: f.write(report) print(f"✓ 报告已保存到: {filepath}") return filepath def send_email_qq(self, report, date): """QQ邮箱专用发送函数""" try: email_config = self.config["email"] subject = f"下周规划提醒 ({date.strftime('%Y-%m-%d')})" msg = MIMEText(report, 'plain', 'utf-8') msg['Subject'] = Header(subject, 'utf-8') msg['From'] = email_config["sender"] msg['To'] = email_config["receiver"] if email_config.get("use_ssl", True): server = smtplib.SMTP_SSL(email_config["smtp_server"], email_config["smtp_port"]) else: server = smtplib.SMTP(email_config["smtp_server"], email_config["smtp_port"]) server.starttls() server.login(email_config["username"], email_config["password"]) server.sendmail(email_config["sender"], [email_config["receiver"]], msg.as_string()) server.quit() print("✓ QQ邮箱邮件发送成功!") return True except Exception as e: print(f"✗ QQ邮箱发送失败: {e}") return False def add_task(self, name, category, hours, priority="medium", recurring=False, recurring_days=None, tags=None): """添加新任务""" if recurring_days is None: recurring_days = [] if tags is None: tags = [] # 生成新任务ID new_id = max([task["id"] for task in self.tasks["tasks"]]) + 1 if self.tasks["tasks"] else 1 new_task = { "id": new_id, "name": name, "category": category, "estimated_hours": hours, "priority": priority, "recurring": recurring, "recurring_days": recurring_days, "status": "pending", "tags": tags, "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S") } self.tasks["tasks"].append(new_task) self.save_tasks(self.tasks) print(f"✓ 任务 '{name}' 添加成功!") return new_id def run(self, send_email=False): """运行规划生成器""" print("=" * 50) print("每周规划生成器") print("=" * 50) # 生成报告 report, next_monday = self.generate_weekly_report() print(report) # 保存到文件 report_file = self.save_report_to_file(report, next_monday) # 发送邮件 if send_email: self.send_email_qq(report, next_monday) print("✓ 下周规划生成完成!") return report_filedef main(): parser = argparse.ArgumentParser(description="每周规划生成器") parser.add_argument("--email", action="store_true", help="发送邮件提醒") parser.add_argument("--add-task", nargs='+', help="添加新任务: 名称 类别 小时数 [优先级]") parser.add_argument("--list-tasks", action="store_true", help="列出所有任务") parser.add_argument("--init", action="store_true", help="初始化配置文件") args = parser.parse_args() planner = WeeklyPlanner() if args.init: print("初始化完成!") print(f"配置文件: {CONFIG_FILE}") print(f"示例任务文件: {TASKS_FILE}") return if args.add_task: # 添加新任务 if len(args.add_task) < 3: print("请提供任务名称、类别和预计小时数") return name = args.add_task[0] category = args.add_task[1] hours = float(args.add_task[2]) priority = args.add_task[3] if len(args.add_task) > 3 else "medium" planner.add_task(name, category, hours, priority) elif args.list_tasks: # 列出所有任务 print("当前所有任务:") print("-" * 50) for task in planner.tasks["tasks"]: status = "🔁" if task.get("recurring") else "✅" if task.get("status") == "completed" else "📝" print(f"{status} [{task['id']}] {task['name']} ({task['category']}, {task['estimated_hours']}h)") else: # 生成每周规划 planner.run(send_email=args.email)if __name__ == "__main__": main()