110 lines
4.1 KiB
Python
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()
|