fix: preserve source body for missing summaries

This commit is contained in:
Codex
2026-06-15 14:53:01 +08:00
parent e2705c269c
commit 6cd1288b18
+62 -3
View File
@@ -13,6 +13,7 @@ sys.path.insert(0, str(ROOT))
from app.data import ( # noqa: E402
append_operation_log,
course_summary_to_class_record_line,
course_summary_semantic_key,
create_course_summary_review_task,
normalize_course_summary,
@@ -192,7 +193,59 @@ def parse_missing_table(path: Path) -> list[dict]:
return rows
def import_missing_tasks(missing_table: Path, tasks_path: Path, dry_run: bool) -> int:
def time_range_from_text(text: str) -> str:
match = re.search(r"(\d{1,2})[:](\d{2})\s*[--–—]\s*(\d{1,2})[:](\d{2})", text)
if not match:
return ""
start_hour, start_minute, end_hour, end_minute = map(int, match.groups())
start = start_hour * 60 + start_minute
end = end_hour * 60 + end_minute
if end <= start:
return ""
return f"{start_hour:02d}:{start_minute:02d}-{end_hour:02d}:{end_minute:02d}"
def duration_from_time_range(time_range: str) -> tuple[str, int | None]:
match = re.fullmatch(r"(\d{2}):(\d{2})-(\d{2}):(\d{2})", time_range)
if not match:
return "", None
start_hour, start_minute, end_hour, end_minute = map(int, match.groups())
minutes = end_hour * 60 + end_minute - (start_hour * 60 + start_minute)
if minutes <= 0:
return "", None
return f"{minutes // 60}小时{minutes % 60}", minutes
def source_summary_for_missing_row(source: Path, row: dict) -> dict:
relative_path = str(row.get("来源文件") or "").strip()
if not relative_path:
return {}
source_path = source / relative_path
if not source_path.exists():
return {}
target_date = str(row.get("日期") or "").replace(".", "-")
best: dict = {}
for entry in iter_markdown_entries(source_path):
if entry.get("date_iso") != target_date:
continue
time_range = str(entry.get("time_range") or "") or time_range_from_text(str(entry.get("body") or ""))
duration, minutes = duration_from_time_range(time_range)
candidate = {
"title": entry.get("title", ""),
"body": entry.get("body", ""),
"time_range": time_range,
"duration": duration,
"duration_minutes": minutes,
}
if time_range:
return candidate
if not best:
best = candidate
return best
def import_missing_tasks(source: Path, missing_table: Path, tasks_path: Path, dry_run: bool) -> int:
rows = parse_missing_table(missing_table)
if not rows:
return 0
@@ -220,12 +273,18 @@ def import_missing_tasks(missing_table: Path, tasks_path: Path, dry_run: bool) -
"teacher_trusted": False,
"remark": row.get("备注", ""),
}
summary.update({key: value for key, value in source_summary_for_missing_row(source, row).items() if value not in ("", None)})
proposed_line = ""
try:
proposed_line = course_summary_to_class_record_line(summary)
except ValueError:
pass
created += 1
if not dry_run:
create_course_summary_review_task(
tasks_path,
summary,
"",
proposed_line,
["历史 classnotes缺失导入,默认只进入审核,不自动扣课时"],
saved_path=row.get("来源文件", ""),
)
@@ -240,7 +299,7 @@ def main() -> None:
missing_table = args.missing_table or (source / "classnotes缺失.txt")
scanned, copied = copy_markdown_files(source, target, args.dry_run)
imported, skipped = rebuild_state_from_markdown(target if target.exists() else source, args.state, args.dry_run)
review_tasks = import_missing_tasks(missing_table, args.tasks, args.dry_run)
review_tasks = import_missing_tasks(source, missing_table, args.tasks, args.dry_run)
if not args.dry_run:
append_operation_log(
args.operation_logs,