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
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user