import pandas as pd from nicegui import ui from config.config import load_config import os def data_page_header(): # 头部样式保持不变,仅补充主体所需的 CSS 变量和类 ui.add_head_html('') ui.add_head_html( """ """ ) with ui.header().classes("app-header items-center justify-between shadow-md px-6"): with ui.row().classes("items-center gap-2"): ui.image("/assets/icon.ico").classes("w-8 h-8").props("fit=contain") ui.label("尚城幼儿园成长报告助手").classes("text-xl font-bold") with ui.row().classes("items-center gap-4"): ui.label("By 寒寒 | 这里的每一份评语都充满爱意").classes( "text-xs opacity-90" ) ui.button(icon="home", on_click=lambda: ui.navigate.to("/")).props( "flat round color=white" ).tooltip("回到首页") def load_data(): conf_data = load_config("config.toml") excel_path = conf_data.get("excel_file") # --- 1. 详情模态框 (UI 升级:档案感排版) --- with ( ui.dialog() as detail_dialog, ui.card().classes( "w-[600px] p-0 profile-dialog rounded-3xl overflow-hidden shadow-2xl" ), ): # 【头部】渐变背景与动态图标 with ui.row().classes( "w-full bg-gradient-to-r from-blue-50 to-indigo-50 items-center justify-between" ): with ui.column().classes("gap-0"): ui.label("幼儿成长档案").classes( "text-xl p-4 font-black text-slate-800" ) ui.button(icon="close", on_click=detail_dialog.close).props( "flat round color=primary" ).classes("bg-white/50") # 【中部】卡片流内容区 with ui.column().classes("w-full p-6 h-[450px] overflow-auto gap-0"): content_container = ui.column().classes("w-full") # 【底部】毛玻璃效果操作栏 with ui.row().classes( "w-full p-5 bg-slate-50/80 backdrop-blur-md border-t justify-end gap-3" ): ui.button("确认", on_click=detail_dialog.close).props( "unelevated color=blue-6" ).classes("px-10 rounded-xl shadow-lg shadow-blue-200 font-bold") def handle_cell_click(e): row_data = e.args["data"] content_container.clear() # 尝试提取名字用于头部(假设你的列名里有“姓名”) student_name = row_data.get("姓名", "详细数据") with content_container: # 顶部增加一个个人摘要卡片 with ui.row().classes( "w-full items-center gap-4 p-4 bg-blue-600 rounded-2xl shadow-md shadow-blue-100" ): ui.avatar("person", color="white", text_color="blue-6").props( "size=48px" ) with ui.column().classes("gap-0 text-white"): ui.label(student_name).classes("text-lg font-bold") # 遍历渲染每一条数据 for key, value in row_data.items(): if key == "姓名": continue # 名字已经显示在摘要里了 with ui.element("div").classes("info-item"): ui.label(key).classes("info-label font-bold text-blue-800") ui.label(str(value)).classes("info-value flex-1") detail_dialog.open() # --- 2. 数据读取与展示 --- if not excel_path or not os.path.exists(excel_path): with ui.column().classes("w-full items-center p-12 text-slate-400"): ui.icon("folder_off", size="64px") ui.label("数据文件未找到,请检查配置路径").classes("mt-4") return try: df = pd.read_excel(excel_path) for col in df.select_dtypes(include=["datetime"]): df[col] = df[col].dt.strftime("%Y-%m-%d") df = df.fillna("-") # 表格上方信息条 with ui.row().classes( "bg-blue-50 w-full p-3 px-6 items-center rounded-t-xl border-b border-blue-100" ): ui.icon("fact_check", color="primary", size="20px") ui.label(f"班级:{conf_data.get('class_name', '未设定')}").classes( "text-sm font-bold text-blue-800" ) ui.separator().props("vertical").classes("mx-2") ui.label(f"共加载 {len(df)} 条幼儿记录").classes("text-xs text-slate-500") ui.space() ui.label("💡 提示:点击行可展开完整评语详情").classes( "text-xs text-amber-600 bg-amber-50 px-2 py-1 rounded" ) # AgGrid (优化表格高度与交互) ui.aggrid( { "columnDefs": [ { "headerName": col, "field": col, "sortable": True, "filter": True, "cellClass": "text-slate-600", "suppressMovable": True, } for col in df.columns ], "rowData": df.to_dict("records"), "pagination": True, "paginationPageSize": 20, "theme": "balham", } ).classes("w-full flex-grow h-[550px] border-none").on( "cellClicked", handle_cell_click ) except Exception as e: ui.notify(f"加载数据时发生错误: {e}", type="negative", position="top") def create_data_page(): data_page_header() with ui.card().classes("w-full m-auto max-w-6xl gap-6"): # 主标题区域 with ui.row().classes("items-end justify-between w-full px-2"): with ui.column().classes("gap-1"): ui.label("数据预览与核对").classes( "text-3xl font-bold text-slate-800 tracking-tight" ) ui.button( "刷新表格", icon="sync", on_click=lambda: ui.navigate.to("/data") ).props("outline color=primary").classes("rounded-lg bg-white shadow-sm") # 数据卡片容器 with ui.card().classes("w-full p-0 data-card rounded-xl overflow-hidden"): load_data()