| import json |
| import gradio as gr |
| import os |
| import re |
|
|
| |
| |
| |
| 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() |
|
|
| |
| |
| |
|
|
| 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 = rec.get("info", "") |
| years = "资料待补充" |
| |
| 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 |
|
|
| |
| |
| |
| with gr.Blocks(title=PROJECT_NAME) as demo: |
| gr.Markdown(f"# 👨👩👧👦 {PROJECT_NAME}") |
| |
| with gr.Tabs(): |
| with gr.Tab("🔍 查亲戚"): |
| gr.Markdown("请输入姓名进行关系链查询") |
|
|
| with gr.Tab("📋 个人资料"): |
| |
| name_input = gr.Textbox(label="输入姓名并回车", placeholder="例如:冯乔福") |
| |
| |
| info_display = gr.Markdown("### 基本信息\n请输入姓名加载数据...") |
| |
| |
| person_photo = gr.Image(label="人物照片", height=300) |
| |
| |
| file_list = gr.Dropdown(label="📁 统一档案检索目录 (文字/音视频)", choices=[]) |
| |
| |
| 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) |