fix: preserve source body for missing summaries
This commit is contained in:
@@ -13,6 +13,7 @@ sys.path.insert(0, str(ROOT))
|
|||||||
|
|
||||||
from app.data import ( # noqa: E402
|
from app.data import ( # noqa: E402
|
||||||
append_operation_log,
|
append_operation_log,
|
||||||
|
course_summary_to_class_record_line,
|
||||||
course_summary_semantic_key,
|
course_summary_semantic_key,
|
||||||
create_course_summary_review_task,
|
create_course_summary_review_task,
|
||||||
normalize_course_summary,
|
normalize_course_summary,
|
||||||
@@ -192,7 +193,59 @@ def parse_missing_table(path: Path) -> list[dict]:
|
|||||||
return rows
|
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)
|
rows = parse_missing_table(missing_table)
|
||||||
if not rows:
|
if not rows:
|
||||||
return 0
|
return 0
|
||||||
@@ -220,12 +273,18 @@ def import_missing_tasks(missing_table: Path, tasks_path: Path, dry_run: bool) -
|
|||||||
"teacher_trusted": False,
|
"teacher_trusted": False,
|
||||||
"remark": row.get("备注", ""),
|
"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
|
created += 1
|
||||||
if not dry_run:
|
if not dry_run:
|
||||||
create_course_summary_review_task(
|
create_course_summary_review_task(
|
||||||
tasks_path,
|
tasks_path,
|
||||||
summary,
|
summary,
|
||||||
"",
|
proposed_line,
|
||||||
["历史 classnotes缺失导入,默认只进入审核,不自动扣课时"],
|
["历史 classnotes缺失导入,默认只进入审核,不自动扣课时"],
|
||||||
saved_path=row.get("来源文件", ""),
|
saved_path=row.get("来源文件", ""),
|
||||||
)
|
)
|
||||||
@@ -240,7 +299,7 @@ def main() -> None:
|
|||||||
missing_table = args.missing_table or (source / "classnotes缺失.txt")
|
missing_table = args.missing_table or (source / "classnotes缺失.txt")
|
||||||
scanned, copied = copy_markdown_files(source, target, args.dry_run)
|
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)
|
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:
|
if not args.dry_run:
|
||||||
append_operation_log(
|
append_operation_log(
|
||||||
args.operation_logs,
|
args.operation_logs,
|
||||||
|
|||||||
Reference in New Issue
Block a user