import json import gradio as gr import os import re # ========================================== # 1. 配置与 CSS (隐藏下载按钮) # ========================================== PROJECT_NAME = "冯氏亲戚关系网" ARCHIVE_ROOT = "archives" PHOTO_ROOT = "photos" CUSTOM_CSS = """ footer {display: none !important;} .download-button {display: none !important;} .share-button {display: none !important;} """ def load_family_data(): db = {} if os.path.exists("family_data.jsonl"): with open("family_data.jsonl", "r", encoding="utf-8") as f: for line in f: try: data = json.loads(line.strip()) if "n" in data: db[data["n"].strip()] = data except: continue return db family_db = load_family_data() # ========================================== # 2. 逻辑函数 # ========================================== def get_person_basic_info(name): """提取基本信息:父母、配偶、生卒""" name = name.strip() if name not in family_db: return "未找到该成员信息", "无", "无", None rec = family_db[name] father = rec.get("f", "不详") mother = rec.get("m", "不详") # 配偶处理 (支持字符串或列表) sp = rec.get("sp", "无") if isinstance(sp, list): sp = "、".join(sp) if sp else "无" # 提取生卒 (简单从 info 中匹配数字) info = rec.get("info", "") years = "资料待补充" # 匹配如 "1900-1980" 或 "1920年出生" year_match = re.findall(r'(\d{4})', info) if len(year_match) >= 2: years = f"{year_match[0]} — {year_match[1]}" elif len(year_match) == 1: years = f"{year_match[0]}年出生" # 查找照片 photo_path = None for ext in ['.jpg', '.png', '.jpeg']: p = os.path.join(PHOTO_ROOT, f"{name}{ext}") if os.path.exists(p): photo_path = p break # 获取档案文件列表 person_dir = os.path.join(ARCHIVE_ROOT, name) files = [] if os.path.exists(person_dir): files = [f for f in os.listdir(person_dir) if os.path.isfile(os.path.join(person_dir, f))] basic_md = f"**父亲:** {father}    **母亲:** {mother}    **配偶:** {sp}\n\n**生卒:** {years}" return basic_md, gr.update(choices=files, value=None), photo_path def handle_file_display(name, filename): """统一展示框逻辑""" if not name or not filename: return [gr.update(visible=False)] * 4 fpath = os.path.join(ARCHIVE_ROOT, name.strip(), filename) ext = os.path.splitext(filename)[1].lower() # 初始化:全部隐藏 res = [gr.update(visible=False, value=None) for _ in range(4)] try: if ext in ['.txt', '.md']: with open(fpath, 'r', encoding='utf-8') as f: res[0] = gr.update(visible=True, value=f.read()) elif ext in ['.jpg', '.png', '.jpeg', '.gif']: res[1] = gr.update(visible=True, value=fpath) elif ext in ['.mp4', '.mov']: res[2] = gr.update(visible=True, value=fpath) elif ext in ['.mp3', '.wav']: res[3] = gr.update(visible=True, value=fpath) except: pass return res # ========================================== # 3. 界面布局 # ========================================== with gr.Blocks(title=PROJECT_NAME) as demo: gr.Markdown(f"# 👨‍👩‍👧‍👦 {PROJECT_NAME}") with gr.Tabs(): with gr.Tab("🔍 查亲戚"): gr.Markdown("请输入姓名进行关系链查询") with gr.Tab("📋 个人资料"): # 1. 顶部:姓名输入 name_input = gr.Textbox(label="输入姓名并回车", placeholder="例如:冯乔福") # 2. 基本信息区域 (父母、配偶、生卒) info_display = gr.Markdown("### 基本信息\n请输入姓名加载数据...") # 3. 照片区域 person_photo = gr.Image(label="人物照片", height=300) # 4. 档案检索 (照片之下) file_list = gr.Dropdown(label="📁 统一档案检索目录 (文字/音视频)", choices=[]) # 5. 统一内容展示 gr.Markdown("---") out_txt = gr.Textbox(label="档案内容", lines=12, visible=False) out_img = gr.Image(label="档案图片", visible=False) out_vid = gr.Video(label="档案视频预览", visible=False) out_aud = gr.Audio(label="档案音频预览", visible=False) # 事件绑定 name_input.submit( fn=get_person_basic_info, inputs=name_input, outputs=[info_display, file_list, person_photo] ) file_list.change( fn=handle_file_display, inputs=[name_input, file_list], outputs=[out_txt, out_img, out_vid, out_aud] ) if __name__ == "__main__": demo.launch(css=CUSTOM_CSS)