Files
openclaw-config/workspace-resume/weekly-reports/migrate_to_mysql.py
T

110 lines
4.1 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""将 SQLite weekly_reports.db 的核心周报数据迁移到 MySQL resume 库。
仅迁移高质量核心数据(标准格式、含每日明细),默认同步全部,可按参数过滤。
用法:
python3 migrate_to_mysql.py # 同步全部 SQLite 周报到 MySQL
python3 migrate_to_mysql.py --dry-run # 只统计不写入
"""
import os
import sqlite3
import sys
import pymysql
BASE = "/home/yangxuan/.openclaw/workspace-resume/weekly-reports"
SQLITE_DB = os.path.join(BASE, "weekly_reports.db")
# MySQL 连接配置
MYSQL_HOST = "127.0.0.1"
MYSQL_PORT = 3306
MYSQL_USER = "root"
MYSQL_DB = "resume"
def get_mysql_pwd():
"""从 .env 读取 MySQL 密码"""
env_path = "/home/yangxuan/.openclaw/.env"
if os.path.exists(env_path):
with open(env_path) as f:
for line in f:
line = line.strip()
if line.startswith("MYSQL_PWD="):
return line.split("=", 1)[1].strip()
return os.environ.get("MYSQL_PWD", "")
def main():
dry_run = "--dry-run" in sys.argv
pwd = get_mysql_pwd()
if not pwd:
print("❌ 未找到 MySQL 密码(MYSQL_PWD),退出")
return
# 1. 读 SQLite
conn = sqlite3.connect(SQLITE_DB)
cur = conn.cursor()
reports = cur.execute(
"SELECT id, year, week_number, start_date, end_date, project, main_task, has_problems, file_path "
"FROM weekly_reports ORDER BY year, week_number").fetchall()
print(f"📂 SQLite 读取到 {len(reports)} 份周报")
# 2. 连接 MySQL
if dry_run:
print("🔍 dry-run 模式:仅统计")
for r in reports:
print(f" W{r[2]:02d} ({r[0]}) {r[1]} | {r[5]} | {r[3]}~{r[4]}")
conn.close()
return
my = pymysql.connect(host=MYSQL_HOST, port=MYSQL_PORT, user=MYSQL_USER,
password=pwd, database=MYSQL_DB, charset="utf8mb4")
myc = my.cursor()
# 3. 逐份插入(UPSERT:先删同 year/week/project 再插,避免冲突)
synced = 0
for (rid, year, wnum, start, end, project, main_task, has_prob, file_path) in reports:
# 清掉同键旧数据
myc.execute(
"DELETE FROM weekly_report_daily WHERE report_id IN "
"(SELECT id FROM weekly_reports WHERE year=%s AND week_number=%s AND project=%s)",
(year, wnum, project))
myc.execute(
"DELETE FROM weekly_report_problems WHERE report_id IN "
"(SELECT id FROM weekly_reports WHERE year=%s AND week_number=%s AND project=%s)",
(year, wnum, project))
myc.execute(
"DELETE FROM weekly_reports WHERE year=%s AND week_number=%s AND project=%s",
(year, wnum, project))
# 插入主表
myc.execute(
"INSERT INTO weekly_reports (year, week_number, start_date, end_date, project, main_task, has_problems, file_path) "
"VALUES (%s,%s,%s,%s,%s,%s,%s,%s)",
(year, wnum, start, end, project, main_task, 1 if has_prob else 0, file_path))
new_id = myc.lastrowid
# 每日明细
daily = cur.execute(
"SELECT day_of_week, work_date, work_items FROM weekly_report_daily WHERE report_id=? ORDER BY work_date",
(rid,)).fetchall()
for (dow, wd, items) in daily:
myc.execute(
"INSERT INTO weekly_report_daily (report_id, day_of_week, work_date, work_items) VALUES (%s,%s,%s,%s)",
(new_id, dow, wd, items))
# 问题
probs = cur.execute(
"SELECT problem_description FROM weekly_report_problems WHERE report_id=?",
(rid,)).fetchall()
for (p_desc,) in probs:
myc.execute(
"INSERT INTO weekly_report_problems (report_id, problem_description) VALUES (%s,%s)",
(new_id, p_desc))
synced += 1
print(f" ✅ W{wnum:02d} ({project}) {start}~{end} | 明细{len(daily)}条 问题{len(probs)}条")
my.commit()
myc.close()
my.close()
conn.close()
print(f"\n🎉 迁移完成:{synced} 份周报已写入 MySQL resume 库")
if __name__ == "__main__":
main()