auto: sync OpenClaw config 2026-08-27 11:17

This commit is contained in:
2026-08-27 11:17:10 +08:00
parent 0269b99815
commit 7a5ca9f1a7
94 changed files with 4497 additions and 2088 deletions
@@ -0,0 +1,308 @@
#!/usr/bin/env python3
"""
周报汇总工具 - 从归档的周报中提取指定时间范围的工作内容
用于月度、年度考核时快速生成工作总结
用法:
python3 summarize_reports.py --week 2026-W31
python3 summarize_reports.py --month 2026-07
python3 summarize_reports.py --year 2026
python3 summarize_reports.py --range 2026-07-01 2026-09-30
"""
import os
import re
import glob
import argparse
from datetime import datetime, timedelta
from pathlib import Path
# 周报归档目录
REPORTS_DIR = Path(__file__).parent
def parse_week_number(week_str):
"""解析周数格式,如 2026-W31"""
match = re.match(r'(\d{4})-W(\d{2})', week_str)
if not match:
return None
year, week = int(match.group(1)), int(match.group(2))
# 计算该周的大致日期范围(简化处理,取第 1 周的周一)
jan_first = datetime(year, 1, 1)
week_start = jan_first + timedelta(weeks=week - 1)
# 调整到最近的周一
week_start = week_start - timedelta(days=week_start.weekday())
week_end = week_start + timedelta(days=4) # 周五
return week_start, week_end
def parse_month_range(month_str):
"""解析月份格式,如 2026-07"""
match = re.match(r'(\d{4})-(\d{2})', month_str)
if not match:
return None
year, month = int(match.group(1)), int(match.group(2))
month_start = datetime(year, month, 1)
if month == 12:
next_month = datetime(year + 1, 1, 1)
else:
next_month = datetime(year, month + 1, 1)
month_end = next_month - timedelta(days=1)
return month_start, month_end
def parse_year_range(year_str):
"""解析年份格式,如 2026"""
match = re.match(r'(\d{4})', year_str)
if not match:
return None
year = int(match.group(1))
year_start = datetime(year, 1, 1)
year_end = datetime(year, 12, 31)
return year_start, year_end
def parse_date_range(start_str, end_str):
"""解析日期范围,如 2026-07-01 2026-09-30"""
try:
start = datetime.strptime(start_str, '%Y-%m-%d')
end = datetime.strptime(end_str, '%Y-%m-%d')
return start, end
except ValueError:
return None
def find_reports_in_range(start_date, end_date):
"""在指定日期范围内查找所有周报文件"""
reports = []
# 遍历所有年份目录
for year_dir in REPORTS_DIR.iterdir():
if not year_dir.is_dir() or year_dir.name.startswith('.'):
continue
# 查找该年份下的所有周报文件
for report_file in glob.glob(str(year_dir / '*.md')):
if report_file.endswith('README.md'):
continue
try:
with open(report_file, 'r', encoding='utf-8') as f:
content = f.read()
# 尝试从文件内容中提取日期范围
date_match = re.search(r'(\d{4}-\d{2}-\d{2})\s*~\s*(\d{4}-\d{2}-\d{2})', content)
if date_match:
file_start = datetime.strptime(date_match.group(1), '%Y-%m-%d')
file_end = datetime.strptime(date_match.group(2), '%Y-%m-%d')
# 检查是否在查询范围内
if file_start <= end_date and file_end >= start_date:
reports.append({
'file': report_file,
'start': file_start,
'end': file_end,
'content': content
})
except Exception as e:
print(f"读取文件失败 {report_file}: {e}")
continue
# 按日期排序
reports.sort(key=lambda x: x['start'])
return reports
def extract_work_content(report_content):
"""从周报内容中提取工作内容"""
sections = {
'project': '',
'task': '',
'daily_work': {},
'problems': ''
}
lines = report_content.split('\n')
current_section = None
current_day = None
for line in lines:
# 项目名称
if line.startswith('项目名称:'):
sections['project'] = line.replace('项目名称:', '').strip()
# 主要任务
elif line.startswith('主要任务:'):
sections['task'] = line.replace('主要任务:', '').strip()
# 本周工作内容
elif '本周工作内容' in line:
current_section = 'daily_work'
# 存在问题
elif line.startswith('存在问题'):
current_section = 'problems'
current_day = None
# 日期行(周一、周二等)
elif current_section == 'daily_work' and re.match(r'^周 [一二三四五六日]\d{4}-\d{2}-\d{2}', line):
match = re.match(r'^周 [一二三四五六日](\d{4}-\d{2}-\d{2})', line)
current_day = match.group(1)
sections['daily_work'][current_day] = []
# 工作内容项
elif current_section == 'daily_work' and line.strip().startswith('- '):
if current_day:
sections['daily_work'][current_day].append(line.strip())
# 问题内容
elif current_section == 'problems' and line.strip() and not line.startswith('存在问题'):
sections['problems'] += line + '\n'
return sections
def generate_summary(reports, summary_type, date_range):
"""生成汇总报告"""
output = []
# 汇总头部
start_str = date_range[0].strftime('%Y-%m-%d')
end_str = date_range[1].strftime('%Y-%m-%d')
output.append(f"# 工作总结报告")
output.append(f"\n**时间范围:** {start_str} ~ {end_str}")
output.append(f"**生成时间:** {datetime.now().strftime('%Y-%m-%d %H:%M')}")
output.append(f"**包含周报数:** {len(reports)}")
output.append("")
# 按项目分组
projects = {}
all_problems = []
all_daily_work = {}
for report in reports:
sections = extract_work_content(report['content'])
project = sections['project'] or '未指定项目'
if project not in projects:
projects[project] = {
'tasks': [],
'weeks': []
}
if sections['task']:
projects[project]['tasks'].append({
'week': f"{report['start'].strftime('%Y-W%W')}",
'task': sections['task']
})
projects[project]['weeks'].append(report['start'].strftime('%Y-W%W'))
# 汇总问题
if sections['problems'].strip():
all_problems.append({
'week': report['start'].strftime('%Y-W%W'),
'problems': sections['problems'].strip()
})
# 汇总每日工作
for day, work_items in sections['daily_work'].items():
if day not in all_daily_work:
all_daily_work[day] = []
all_daily_work[day].extend(work_items)
# 输出项目汇总
output.append("## 📊 项目汇总\n")
for project, data in projects.items():
output.append(f"### {project}")
weeks = sorted(set(data['weeks']))
output.append(f"**参与周次:** {', '.join(weeks)}")
output.append(f"**主要任务:**")
for item in data['tasks']:
output.append(f"- {item['week']}: {item['task']}")
output.append("")
# 输出存在问题汇总
if all_problems:
output.append("## ⚠️ 存在问题汇总\n")
for item in all_problems:
output.append(f"### {item['week']}")
output.append(item['problems'])
output.append("")
# 输出所有周报原文(可选)
output.append("\n---\n")
output.append("## 📋 原始周报记录\n")
for report in reports:
week_str = report['start'].strftime('%Y-W%W')
output.append(f"\n### {week_str} ({report['start'].strftime('%Y-%m-%d')} ~ {report['end'].strftime('%Y-%m-%d')})")
output.append(f"文件:{report['file']}\n")
# 提取周报的前 20 行作为摘要
preview_lines = report['content'].split('\n')[:20]
output.append('\n'.join(preview_lines))
output.append("\n... (更多内容见原文件)\n")
return '\n'.join(output)
def main():
parser = argparse.ArgumentParser(description='周报汇总工具')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('--week', type=str, help='指定周数,如 2026-W31')
group.add_argument('--month', type=str, help='指定月份,如 2026-07')
group.add_argument('--year', type=str, help='指定年份,如 2026')
group.add_argument('--range', type=str, nargs=2, metavar=('START', 'END'), help='指定日期范围,如 2026-07-01 2026-09-30')
args = parser.parse_args()
# 解析日期范围
date_range = None
summary_type = None
if args.week:
date_range = parse_week_number(args.week)
summary_type = 'week'
elif args.month:
date_range = parse_month_range(args.month)
summary_type = 'month'
elif args.year:
date_range = parse_year_range(args.year)
summary_type = 'year'
elif args.range:
date_range = parse_date_range(args.range[0], args.range[1])
summary_type = 'range'
if not date_range:
print("❌ 日期格式错误")
return 1
print(f"🔍 查找范围:{date_range[0].strftime('%Y-%m-%d')} ~ {date_range[1].strftime('%Y-%m-%d')}")
# 查找周报
reports = find_reports_in_range(date_range[0], date_range[1])
if not reports:
print("❌ 未找到符合条件的周报")
return 1
print(f"✅ 找到 {len(reports)} 份周报")
# 生成汇总
summary = generate_summary(reports, summary_type, date_range)
# 输出到文件
output_file = f"summary_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md"
with open(output_file, 'w', encoding='utf-8') as f:
f.write(summary)
print(f"📄 汇总报告已生成:{output_file}")
print("\n" + "="*50)
print(summary[:2000]) # 预览前 2000 字符
if len(summary) > 2000:
print(f"\n... (共 {len(summary)} 字符,完整内容见 {output_file})")
return 0
if __name__ == '__main__':
exit(main())