from io import BytesIO from pathlib import Path from openpyxl import Workbook, load_workbook QUESTION_COLUMNS = [ ("chapter", "章节"), ("primary_knowledge", "一级知识点"), ("secondary_knowledge", "二级知识点"), ("question_type", "题目类型"), ("difficulty", "难度"), ("stem", "题干"), ("option_a", "选项A"), ("option_b", "选项B"), ("option_c", "选项C"), ("option_d", "选项D"), ("answer", "正确答案"), ("explanation", "解析"), ("notes", "备注"), ("source_file", "来源文件"), ] def create_template_bytes() -> bytes: wb = Workbook() ws = wb.active ws.title = "questions" ws.append([col[1] for col in QUESTION_COLUMNS]) ws.append(["函数", "", "函数性质", "单选", "中", "示例题干", "A", "B", "C", "D", "A", "示例解析", "", "template.xlsx"]) buf = BytesIO() wb.save(buf) return buf.getvalue() def parse_excel_file(path: Path) -> list[dict]: wb = load_workbook(path, read_only=True) ws = wb.active rows = list(ws.iter_rows(values_only=True)) if not rows: return [] headers = [str(v).strip() if v is not None else "" for v in rows[0]] key_map = {label: key for key, label in QUESTION_COLUMNS} result: list[dict] = [] for row in rows[1:]: if not row or all(v is None or str(v).strip() == "" for v in row): continue item = {key: "" for key, _ in QUESTION_COLUMNS} for idx, val in enumerate(row): if idx >= len(headers): continue label = headers[idx] key = key_map.get(label) if not key: continue item[key] = "" if val is None else str(val) if item["stem"]: result.append(item) return result def export_excel_bytes(items: list[dict]) -> bytes: wb = Workbook() ws = wb.active ws.title = "questions" ws.append([label for _, label in QUESTION_COLUMNS]) for item in items: ws.append([item.get(key, "") for key, _ in QUESTION_COLUMNS]) buf = BytesIO() wb.save(buf) return buf.getvalue()