Files
aiagent/scripts/tools/daily_work_summary.py
renjianbo eabf90c496 feat: add AI学习助手 agent (KG+RAG ideal) and renshenguo feishu bot
- Add AI学习助手 agent creation script with all 39 tools, 3-layer KG+RAG memory
- Add renshenguo (人参果) feishu bot integration (app_service + ws_handler)
- Register renshenguo WS client in main.py startup
- Add RENSHENGUO_APP_ID / RENSHENGUO_APP_SECRET / RENSHENGUO_AGENT_ID config
- Reorganize docs from root into docs/ subdirectories
- Move startup scripts to scripts/startup/
- Various backend optimizations and tool improvements

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-06 01:37:13 +08:00

404 lines
14 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================================
📋 每日工作总结自动生成器
功能每天早上9点 → 生成今日工作总结 → 推送到指定渠道
===========================================
"""
import json
import os
import sys
import datetime
import smtplib
import requests
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from pathlib import Path
# ===========================================
# 📝 第一部分:配置区(请按需修改)
# ===========================================
class Config:
"""所有配置集中管理,方便修改"""
# --- 数据来源方式 ---
# mode = "manual" → 手动输入今日事项
# mode = "file" → 从文件读取今日事项
DATA_MODE = "manual"
# 当 DATA_MODE = "file" 时,读取此文件
DATA_FILE = "today_work_items.txt"
# --- 推送方式(可多选)---
# 支持wecom企业微信、dingtalk钉钉、email邮件
PUSH_CHANNELS = ["wecom"] # 可改为 ["dingtalk"] 或 ["email"]
# ----- 企业微信机器人 -----
WECOM_WEBHOOK = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY_HERE"
# ----- 钉钉机器人 -----
DINGTALK_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN_HERE"
# ----- 邮件配置 -----
SMTP_SERVER = "smtp.qq.com"
SMTP_PORT = 465
SMTP_USER = "your_email@qq.com"
SMTP_PASSWORD = "your_auth_code" # 邮件授权码,非密码
MAIL_TO = ["boss@company.com", "yourself@company.com"]
# --- 总结模板 ---
SUMMARY_TEMPLATE = """
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📅 今日工作总结 · {date}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
👤 姓名:{name}
🏢 部门:{department}
📌 今日工作事项:
{work_items}
📊 工作总结:
{summary}
✅ 明日计划:
{tomorrow_plan}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⏰ 生成时间:{generate_time}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
"""
# ===========================================
# 🔧 第二部分:核心功能
# ===========================================
class WorkSummaryGenerator:
"""工作总结生成器"""
def __init__(self, name="张三", department="技术部"):
self.name = name
self.department = department
self.today = datetime.date.today()
self.tomorrow = self.today + datetime.timedelta(days=1)
def get_work_items_from_input(self):
"""方式一:手动输入今日工作事项"""
print("\n📝 请输入你今天的工作事项(每行一条,输入空行结束):")
print("完成了XX功能开发 / 修复了XXbug / 参加了XX会议\n")
items = []
while True:
line = input("").strip()
if not line:
break
items.append(line)
return items
def get_work_items_from_file(self, filepath):
"""方式二:从文件读取今日工作事项"""
try:
with open(filepath, "r", encoding="utf-8") as f:
items = [line.strip() for line in f if line.strip()]
return items
except FileNotFoundError:
print(f"⚠️ 文件 {filepath} 不存在,请先创建!")
return []
def generate_summary(self, work_items):
"""生成工作总结(基于规则+模板你也可以接入AI API"""
if not work_items:
return "今日暂无工作记录。"
# 统计信息
total_items = len(work_items)
# 简单分类统计(关键词匹配)
categories = {
"开发": 0, "修复": 0, "会议": 0, "文档": 0,
"测试": 0, "沟通": 0, "其他": 0
}
keywords_map = {
"开发": ["开发", "编码", "编程", "实现", "搭建", "构建"],
"修复": ["修复", "解决", "处理", "修改", "bug", "Bug"],
"会议": ["会议", "评审", "讨论", "沟通会", "晨会", "周会"],
"文档": ["文档", "文档", "方案", "设计", "PPT", "报告"],
"测试": ["测试", "调试", "自测", "联调", "验证"],
"沟通": ["沟通", "对齐", "同步", "协调", "对接"],
}
for item in work_items:
matched = False
for cat, keywords in keywords_map.items():
if any(kw in item for kw in keywords):
categories[cat] += 1
matched = True
break
if not matched:
categories["其他"] += 1
# 生成总结文本
summary_parts = [f"今日共完成 {total_items} 项工作,具体如下:\n"]
# 分类汇总
active_cats = {k: v for k, v in categories.items() if v > 0}
if active_cats:
summary_parts.append("📊 工作类型分布:")
for cat, count in active_cats.items():
bar = "" * count
summary_parts.append(f" {cat}{bar} {count}")
summary_parts.append("")
# 逐项列出
summary_parts.append("📋 详细工作记录:")
for i, item in enumerate(work_items, 1):
summary_parts.append(f" {i}. {item}")
# 评价与建议
summary_parts.append(f"\n💡 今日小结:今日工作效率{'较高' if total_items >= 5 else '正常'}"
f"建议明日继续保持{'/优化时间管理' if total_items < 3 else ''}")
return "\n".join(summary_parts)
def generate_tomorrow_plan(self):
"""生成明日计划(可扩展为从配置文件读取)"""
plan_items = [
"继续推进当前开发任务",
"同步项目进度",
"代码审查",
]
return "\n".join(f" {i+1}. {item}" for i, item in enumerate(plan_items))
def build_summary_text(self, work_items, summary):
"""组装完整的总结文本"""
tomorrow_plan = self.generate_tomorrow_plan()
formatted_items = "\n".join(f"{item}" for item in work_items)
now_str = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return Config.SUMMARY_TEMPLATE.format(
date=self.today.strftime("%Y年%m月%d"),
name=self.name,
department=self.department,
work_items=formatted_items if formatted_items else " (暂无记录)",
summary=summary,
tomorrow_plan=tomorrow_plan,
generate_time=now_str
)
def run(self):
"""主运行流程"""
print(f"\n{'='*50}")
print(f"📅 今日工作总结生成器")
print(f"📆 {self.today.strftime('%Y年%m月%d')}")
print(f"{'='*50}\n")
# 1⃣ 获取工作事项
if Config.DATA_MODE == "file":
items = self.get_work_items_from_file(Config.DATA_FILE)
else:
items = self.get_work_items_from_input()
if not items:
print("⚠️ 没有输入任何工作事项,将生成空总结。")
# 2⃣ 生成总结
summary = self.generate_summary(items)
final_text = self.build_summary_text(items, summary)
# 3⃣ 本地保存
self.save_to_file(final_text)
# 4⃣ 推送
pusher = MessagePusher()
pusher.push(final_text)
return final_text
def save_to_file(self, content):
"""保存到本地文件"""
filename = f"工作总结_{self.today.strftime('%Y%m%d')}.md"
with open(filename, "w", encoding="utf-8") as f:
f.write(content)
print(f"\n✅ 已保存到本地文件:{os.path.abspath(filename)}")
# ===========================================
# 📨 第三部分:消息推送
# ===========================================
class MessagePusher:
"""消息推送器"""
def push(self, content):
"""根据配置推送消息到各个渠道"""
for channel in Config.PUSH_CHANNELS:
if channel == "wecom":
self.push_wecom(content)
elif channel == "dingtalk":
self.push_dingtalk(content)
elif channel == "email":
self.push_email(content)
else:
print(f"⚠️ 未知推送渠道: {channel}")
def push_wecom(self, content):
"""推送到企业微信机器人"""
url = Config.WECOM_WEBHOOK
if "YOUR_KEY_HERE" in url:
print("⚠️ 跳过企业微信推送未配置Webhook地址")
return
data = {
"msgtype": "markdown",
"markdown": {"content": content}
}
try:
resp = requests.post(url, json=data, timeout=10)
result = resp.json()
if result.get("errcode") == 0:
print("✅ 企业微信推送成功!")
else:
print(f"⚠️ 企业微信推送失败: {result}")
except Exception as e:
print(f"⚠️ 企业微信推送异常: {e}")
def push_dingtalk(self, content):
"""推送到钉钉机器人"""
url = Config.DINGTALK_WEBHOOK
if "YOUR_TOKEN_HERE" in url:
print("⚠️ 跳过钉钉推送未配置Webhook地址")
return
data = {
"msgtype": "markdown",
"markdown": {
"title": "今日工作总结",
"text": content
}
}
try:
resp = requests.post(url, json=data, timeout=10)
result = resp.json()
if result.get("errcode") == 0:
print("✅ 钉钉推送成功!")
else:
print(f"⚠️ 钉钉推送失败: {result}")
except Exception as e:
print(f"⚠️ 钉钉推送异常: {e}")
def push_email(self, content):
"""通过邮件推送"""
if "your_email" in Config.SMTP_USER:
print("⚠️ 跳过邮件推送:未配置邮箱信息")
return
try:
msg = MIMEMultipart()
msg["From"] = Config.SMTP_USER
msg["To"] = ", ".join(Config.MAIL_TO)
msg["Subject"] = f"今日工作总结 - {datetime.date.today().strftime('%Y-%m-%d')}"
msg.attach(MIMEText(content, "plain", "utf-8"))
with smtplib.SMTP_SSL(Config.SMTP_SERVER, Config.SMTP_PORT) as server:
server.login(Config.SMTP_USER, Config.SMTP_PASSWORD)
server.sendmail(Config.SMTP_USER, Config.MAIL_TO, msg.as_string())
print("✅ 邮件推送成功!")
except Exception as e:
print(f"⚠️ 邮件推送异常: {e}")
# ===========================================
# 🚀 第四部分:程序入口
# ===========================================
def setup_windows_task():
"""生成Windows任务计划程序导入脚本"""
script_path = os.path.abspath(sys.argv[0])
python_path = sys.executable
cmd = f'''@echo off
echo ========================================
echo 设置每日9点自动运行工作总结脚本
echo ========================================
REM 请以管理员身份运行此.bat文件
schtasks /create /tn "每日工作总结" /tr "{python_path} {script_path}" /sc daily /st 09:00 /f
if %errorlevel%==0 (
echo ✅ 定时任务创建成功每天早上9:00自动运行。
) else (
echo ❌ 创建失败,请尝试以管理员身份运行。
)
pause
'''
bat_path = "setup_windows_task.bat"
with open(bat_path, "w", encoding="utf-8") as f:
f.write(cmd)
print(f"\n📁 Windows定时任务脚本已生成{os.path.abspath(bat_path)}")
print(" → 右键点击该文件,选择「以管理员身份运行」即可设置定时任务!")
def setup_linux_cron():
"""输出Linux crontab配置说明"""
script_path = os.path.abspath(sys.argv[0])
python_path = sys.executable
print("\n" + "="*50)
print("🐧 Linux/macOS 定时任务设置crontab")
print("="*50)
print(f"在终端中执行以下命令添加定时任务:")
print(f"\n crontab -e")
print(f"\n然后添加一行:")
print(f"\n 0 9 * * * {python_path} {script_path}")
print(f"\n保存退出即可!📌")
if __name__ == "__main__":
import sys
# 检查是否有命令行参数
if len(sys.argv) > 1:
arg = sys.argv[1].lower()
if arg == "--setup-win":
setup_windows_task()
sys.exit(0)
elif arg == "--setup-linux":
setup_linux_cron()
sys.exit(0)
print("""
╔══════════════════════════════════════════╗
║ 🍊 每日工作总结生成器 ║
║ ║
║ 用法: ║
║ python daily_work_summary.py ║
║ python daily_work_summary.py --setup-win ║
║ python daily_work_summary.py --setup-linux ║
╚══════════════════════════════════════════╝
""")
# 运行主程序
generator = WorkSummaryGenerator(name="张三", department="技术部")
result = generator.run()
print("\n" + "="*50)
print("🎉 工作总结生成完成!")
print("="*50)
# 生成本地定时任务设置脚本
if sys.platform == "win32":
setup_windows_task()
else:
setup_linux_cron()
print("\n💡 小提示:修改 config.py 中的配置可自定义推送到不同渠道~")