Răsfoiți Sursa

commit 优化展示

林海 13 ore în urmă
părinte
comite
d151b48ccf
3 a modificat fișierele cu 143 adăugiri și 46 ștergeri
  1. 43 22
      app.py
  2. 16 16
      templates/add_member.html
  3. 84 8
      templates/lineage_query.html

+ 43 - 22
app.py

@@ -1673,22 +1673,43 @@ def search_member():
         return jsonify({"success": False, "message": "Unauthorized"}), 401
         return jsonify({"success": False, "message": "Unauthorized"}), 401
     
     
     data = request.get_json()
     data = request.get_json()
-    keyword = data.get('keyword', '').strip()
-    
+    keyword     = data.get('keyword', '').strip()
+    search_type = data.get('search_type', 'name')  # name | former_name | childhood_name | name_word
+
     if not keyword:
     if not keyword:
         return jsonify({"success": False, "message": "请输入搜索关键词"})
         return jsonify({"success": False, "message": "请输入搜索关键词"})
-    
+
     conn = get_db_connection()
     conn = get_db_connection()
     try:
     try:
         with conn.cursor() as cursor:
         with conn.cursor() as cursor:
-            # 先去重查人员(每个 ID 只返回一行),再子查询附加父亲和出继信息
             like = f'%{keyword}%'
             like = f'%{keyword}%'
-            cursor.execute("""
+            # 根据搜索类型构建 WHERE 子句
+            if search_type == 'former_name':
+                where_clause = "fmi.former_name LIKE %s"
+                where_params = (like,)
+                order_params = (keyword, keyword, f'{keyword}%', f'{keyword}%')
+            elif search_type == 'childhood_name':
+                where_clause = "fmi.childhood_name LIKE %s"
+                where_params = (like,)
+                order_params = (keyword, keyword, f'{keyword}%', f'{keyword}%')
+            elif search_type == 'name_word':
+                where_clause = "fmi.name_word LIKE %s"
+                where_params = (like,)
+                order_params = (keyword, keyword, f'{keyword}%', f'{keyword}%')
+            else:  # name(默认:姓名搜索)
+                where_clause = "fmi.name LIKE %s OR fmi.simplified_name LIKE %s OR fmi.former_name LIKE %s"
+                where_params = (like, like, like)
+                order_params = (keyword, keyword, f'{keyword}%', f'{keyword}%')
+
+            cursor.execute(f"""
                 SELECT
                 SELECT
                     fmi.id,
                     fmi.id,
                     fmi.name,
                     fmi.name,
                     fmi.simplified_name,
                     fmi.simplified_name,
                     fmi.name_word_generation,
                     fmi.name_word_generation,
+                    fmi.former_name,
+                    fmi.childhood_name,
+                    fmi.name_word,
                     -- 父亲:优先非入继父(sub_type != 3),取第一条
                     -- 父亲:优先非入继父(sub_type != 3),取第一条
                     (SELECT p.name FROM family_relation_info r
                     (SELECT p.name FROM family_relation_info r
                      JOIN family_member_info p ON r.parent_mid = p.id
                      JOIN family_member_info p ON r.parent_mid = p.id
@@ -1700,7 +1721,7 @@ def search_member():
                      WHERE r.child_mid = fmi.id AND r.relation_type = 1
                      WHERE r.child_mid = fmi.id AND r.relation_type = 1
                      ORDER BY CASE WHEN COALESCE(r.sub_relation_type,0)=3 THEN 1 ELSE 0 END, r.id
                      ORDER BY CASE WHEN COALESCE(r.sub_relation_type,0)=3 THEN 1 ELSE 0 END, r.id
                      LIMIT 1) AS father_simplified_name,
                      LIMIT 1) AS father_simplified_name,
-                    -- 出继标注:同时有 sub_type=2(亲生方)和 sub_type=3(养家方)时生成
+                    -- 出继标注
                     (SELECT CONCAT(
                     (SELECT CONCAT(
                          '出继自',
                          '出继自',
                          COALESCE(pbio.simplified_name, pbio.name, '?'),
                          COALESCE(pbio.simplified_name, pbio.name, '?'),
@@ -1713,7 +1734,7 @@ def search_member():
                      WHERE rbio.child_mid = fmi.id AND rbio.sub_relation_type = 2
                      WHERE rbio.child_mid = fmi.id AND rbio.sub_relation_type = 2
                      LIMIT 1) AS adoption_note
                      LIMIT 1) AS adoption_note
                 FROM family_member_info fmi
                 FROM family_member_info fmi
-                WHERE fmi.name LIKE %s OR fmi.simplified_name LIKE %s OR fmi.former_name LIKE %s
+                WHERE {where_clause}
                 GROUP BY fmi.id
                 GROUP BY fmi.id
                 ORDER BY
                 ORDER BY
                     CASE WHEN fmi.name = %s THEN 1
                     CASE WHEN fmi.name = %s THEN 1
@@ -1721,7 +1742,7 @@ def search_member():
                          WHEN fmi.name LIKE %s THEN 3
                          WHEN fmi.name LIKE %s THEN 3
                          WHEN fmi.simplified_name LIKE %s THEN 4
                          WHEN fmi.simplified_name LIKE %s THEN 4
                          ELSE 5 END
                          ELSE 5 END
-            """, (like, like, like, keyword, keyword, f'{keyword}%', f'{keyword}%'))
+            """, (*where_params, *order_params))
             members = cursor.fetchall()
             members = cursor.fetchall()
 
 
             if not members:
             if not members:
@@ -1793,7 +1814,7 @@ def get_lineage(member_id):
             for depth in range(max_depth):
             for depth in range(max_depth):
                 # 获取所有父母关系(支持出继/入继)
                 # 获取所有父母关系(支持出继/入继)
                 cursor.execute("""
                 cursor.execute("""
-                    SELECT p.id, p.name, p.simplified_name, p.name_word, p.name_word_generation,
+                    SELECT p.id, p.name, p.simplified_name, p.name_word, p.name_word_generation, p.former_name, p.childhood_name,
                            EXISTS(SELECT 1 FROM family_relation_info WHERE parent_mid = p.id AND relation_type IN (1, 2)) as has_children,
                            EXISTS(SELECT 1 FROM family_relation_info WHERE parent_mid = p.id AND relation_type IN (1, 2)) as has_children,
                            r.sub_relation_type
                            r.sub_relation_type
                     FROM family_relation_info r
                     FROM family_relation_info r
@@ -1875,7 +1896,7 @@ def get_lineage(member_id):
 
 
                     # 获取祖先的兄弟(含 child_order 和 sub_relation_type,用于出继/入继标注)
                     # 获取祖先的兄弟(含 child_order 和 sub_relation_type,用于出继/入继标注)
                     cursor.execute("""
                     cursor.execute("""
-                        SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation,
+                        SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation, c.former_name, c.childhood_name,
                                EXISTS(SELECT 1 FROM family_relation_info WHERE parent_mid = c.id AND relation_type IN (1, 2)) as has_children,
                                EXISTS(SELECT 1 FROM family_relation_info WHERE parent_mid = c.id AND relation_type IN (1, 2)) as has_children,
                                COALESCE(r.child_order, NULL) AS child_order,
                                COALESCE(r.child_order, NULL) AS child_order,
                                r.sub_relation_type
                                r.sub_relation_type
@@ -1950,7 +1971,7 @@ def get_lineage(member_id):
                   )"""
                   )"""
 
 
             cursor.execute(f"""
             cursor.execute(f"""
-                SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation,
+                SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation, c.former_name, c.childhood_name,
                        EXISTS(SELECT 1 FROM family_relation_info WHERE parent_mid = c.id AND relation_type IN (1, 2)) as has_children,
                        EXISTS(SELECT 1 FROM family_relation_info WHERE parent_mid = c.id AND relation_type IN (1, 2)) as has_children,
                        r.sub_relation_type,
                        r.sub_relation_type,
                        r.child_order
                        r.child_order
@@ -2011,7 +2032,7 @@ def get_lineage(member_id):
                 center_child_order = co_row['child_order'] if co_row else None
                 center_child_order = co_row['child_order'] if co_row else None
 
 
                 cursor.execute("""
                 cursor.execute("""
-                    SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation,
+                    SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation, c.former_name, c.childhood_name,
                            EXISTS(SELECT 1 FROM family_relation_info WHERE parent_mid = c.id AND relation_type IN (1, 2)) as has_children,
                            EXISTS(SELECT 1 FROM family_relation_info WHERE parent_mid = c.id AND relation_type IN (1, 2)) as has_children,
                            r.sub_relation_type,
                            r.sub_relation_type,
                            COALESCE(r.child_order, NULL) AS child_order
                            COALESCE(r.child_order, NULL) AS child_order
@@ -2108,7 +2129,7 @@ def get_ancestors_above(ancestor_id):
 
 
             for depth in range(max_depth):
             for depth in range(max_depth):
                 cursor.execute("""
                 cursor.execute("""
-                    SELECT p.id, p.name, p.simplified_name, p.name_word, p.name_word_generation,
+                    SELECT p.id, p.name, p.simplified_name, p.name_word, p.name_word_generation, p.former_name, p.childhood_name,
                            EXISTS(SELECT 1 FROM family_relation_info
                            EXISTS(SELECT 1 FROM family_relation_info
                                   WHERE parent_mid = p.id AND relation_type IN (1,2)) as has_children,
                                   WHERE parent_mid = p.id AND relation_type IN (1,2)) as has_children,
                            r.sub_relation_type
                            r.sub_relation_type
@@ -2178,7 +2199,7 @@ def get_ancestors_above(ancestor_id):
                     parent['child_order'] = co_row['child_order'] if co_row else 1
                     parent['child_order'] = co_row['child_order'] if co_row else 1
 
 
                     cursor.execute("""
                     cursor.execute("""
-                        SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation,
+                        SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation, c.former_name, c.childhood_name,
                                EXISTS(SELECT 1 FROM family_relation_info
                                EXISTS(SELECT 1 FROM family_relation_info
                                       WHERE parent_mid = c.id AND relation_type IN (1,2)) as has_children,
                                       WHERE parent_mid = c.id AND relation_type IN (1,2)) as has_children,
                                COALESCE(r.child_order, 1) AS child_order
                                COALESCE(r.child_order, 1) AS child_order
@@ -2248,7 +2269,7 @@ def get_descendants(parent_id):
                 # Build query with exclusion
                 # Build query with exclusion
                 placeholders = ', '.join(['%s'] * len(excluded_list))
                 placeholders = ', '.join(['%s'] * len(excluded_list))
                 cursor.execute(f"""
                 cursor.execute(f"""
-                    SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation,
+                    SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation, c.former_name, c.childhood_name,
                            EXISTS(SELECT 1 FROM family_relation_info WHERE parent_mid = c.id AND relation_type IN (1, 2)) as has_children
                            EXISTS(SELECT 1 FROM family_relation_info WHERE parent_mid = c.id AND relation_type IN (1, 2)) as has_children
                     FROM family_relation_info r
                     FROM family_relation_info r
                     JOIN family_member_info c ON r.child_mid = c.id
                     JOIN family_member_info c ON r.child_mid = c.id
@@ -2258,7 +2279,7 @@ def get_descendants(parent_id):
                 """, (parent_id,) + tuple(excluded_list))
                 """, (parent_id,) + tuple(excluded_list))
             else:
             else:
                 cursor.execute("""
                 cursor.execute("""
-                    SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation,
+                    SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation, c.former_name, c.childhood_name,
                            EXISTS(SELECT 1 FROM family_relation_info WHERE parent_mid = c.id AND relation_type IN (1, 2)) as has_children
                            EXISTS(SELECT 1 FROM family_relation_info WHERE parent_mid = c.id AND relation_type IN (1, 2)) as has_children
                     FROM family_relation_info r
                     FROM family_relation_info r
                     JOIN family_member_info c ON r.child_mid = c.id
                     JOIN family_member_info c ON r.child_mid = c.id
@@ -6064,7 +6085,7 @@ def api_get_lineage(member_id):
 
 
             for depth in range(max_depth):
             for depth in range(max_depth):
                 cursor.execute("""
                 cursor.execute("""
-                    SELECT p.id, p.name, p.simplified_name, p.name_word, p.name_word_generation,
+                    SELECT p.id, p.name, p.simplified_name, p.name_word, p.name_word_generation, p.former_name, p.childhood_name,
                            EXISTS(SELECT 1 FROM family_relation_info
                            EXISTS(SELECT 1 FROM family_relation_info
                                   WHERE parent_mid = p.id AND relation_type IN (1,2)) as has_children,
                                   WHERE parent_mid = p.id AND relation_type IN (1,2)) as has_children,
                            r.sub_relation_type
                            r.sub_relation_type
@@ -6136,7 +6157,7 @@ def api_get_lineage(member_id):
                     parent['child_order'] = co_row['child_order'] if co_row else 1
                     parent['child_order'] = co_row['child_order'] if co_row else 1
 
 
                     cursor.execute("""
                     cursor.execute("""
-                        SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation,
+                        SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation, c.former_name, c.childhood_name,
                                EXISTS(SELECT 1 FROM family_relation_info
                                EXISTS(SELECT 1 FROM family_relation_info
                                       WHERE parent_mid = c.id AND relation_type IN (1,2)) as has_children,
                                       WHERE parent_mid = c.id AND relation_type IN (1,2)) as has_children,
                                COALESCE(r.child_order, 1) AS child_order
                                COALESCE(r.child_order, 1) AS child_order
@@ -6162,7 +6183,7 @@ def api_get_lineage(member_id):
 
 
             # Step 3: 获取子女(排除出继、保留入继,带排行)
             # Step 3: 获取子女(排除出继、保留入继,带排行)
             cursor.execute("""
             cursor.execute("""
-                SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation,
+                SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation, c.former_name, c.childhood_name,
                        EXISTS(SELECT 1 FROM family_relation_info
                        EXISTS(SELECT 1 FROM family_relation_info
                               WHERE parent_mid = c.id AND relation_type IN (1,2)) as has_children,
                               WHERE parent_mid = c.id AND relation_type IN (1,2)) as has_children,
                        COALESCE(r.child_order, 1) AS child_order, r.sub_relation_type
                        COALESCE(r.child_order, 1) AS child_order, r.sub_relation_type
@@ -6212,7 +6233,7 @@ def api_get_lineage(member_id):
                 center_child_order = (co_row['child_order'] if co_row and co_row['child_order'] else 1)
                 center_child_order = (co_row['child_order'] if co_row and co_row['child_order'] else 1)
 
 
                 cursor.execute("""
                 cursor.execute("""
-                    SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation,
+                    SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation, c.former_name, c.childhood_name,
                            EXISTS(SELECT 1 FROM family_relation_info
                            EXISTS(SELECT 1 FROM family_relation_info
                                   WHERE parent_mid = c.id AND relation_type IN (1,2)) as has_children,
                                   WHERE parent_mid = c.id AND relation_type IN (1,2)) as has_children,
                            r.sub_relation_type, COALESCE(r.child_order, 1) AS child_order
                            r.sub_relation_type, COALESCE(r.child_order, 1) AS child_order
@@ -6292,7 +6313,7 @@ def api_get_ancestors_above(ancestor_id):
 
 
             for depth in range(max_depth):
             for depth in range(max_depth):
                 cursor.execute("""
                 cursor.execute("""
-                    SELECT p.id, p.name, p.simplified_name, p.name_word, p.name_word_generation,
+                    SELECT p.id, p.name, p.simplified_name, p.name_word, p.name_word_generation, p.former_name, p.childhood_name,
                            EXISTS(SELECT 1 FROM family_relation_info
                            EXISTS(SELECT 1 FROM family_relation_info
                                   WHERE parent_mid = p.id AND relation_type IN (1,2)) as has_children,
                                   WHERE parent_mid = p.id AND relation_type IN (1,2)) as has_children,
                            r.sub_relation_type
                            r.sub_relation_type
@@ -6358,7 +6379,7 @@ def api_get_ancestors_above(ancestor_id):
                     parent['child_order'] = co_row['child_order'] if co_row else 1
                     parent['child_order'] = co_row['child_order'] if co_row else 1
 
 
                     cursor.execute("""
                     cursor.execute("""
-                        SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation,
+                        SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation, c.former_name, c.childhood_name,
                                EXISTS(SELECT 1 FROM family_relation_info
                                EXISTS(SELECT 1 FROM family_relation_info
                                       WHERE parent_mid = c.id AND relation_type IN (1,2)) as has_children,
                                       WHERE parent_mid = c.id AND relation_type IN (1,2)) as has_children,
                                COALESCE(r.child_order, 1) AS child_order
                                COALESCE(r.child_order, 1) AS child_order

+ 16 - 16
templates/add_member.html

@@ -184,6 +184,22 @@
                             <label class="form-label">堂内排行</label>
                             <label class="form-label">堂内排行</label>
                             <input type="text" name="family_rank" class="form-control" value="{{ member.family_rank if member else '' }}">
                             <input type="text" name="family_rank" class="form-control" value="{{ member.family_rank if member else '' }}">
                         </div>
                         </div>
+                        <div class="col-md-3">
+                            <label class="form-label">曾用名</label>
+                            <input type="text" name="former_name" class="form-control" placeholder="曾用名(选填)" value="{{ member.former_name if member and member.former_name else '' }}">
+                        </div>
+                        <div class="col-md-3">
+                            <label class="form-label">幼名 / 乳名</label>
+                            <input type="text" name="childhood_name" class="form-control" placeholder="幼名或乳名(选填)" value="{{ member.childhood_name if member and member.childhood_name else '' }}">
+                        </div>
+                        <div class="col-md-3">
+                            <label class="form-label">字辈</label>
+                            <input type="text" name="name_word" class="form-control" placeholder="字辈(选填)" value="{{ member.name_word if member and member.name_word else '' }}">
+                        </div>
+                        <div class="col-md-3">
+                            <label class="form-label">名号 / 封号</label>
+                            <input type="text" name="name_title" class="form-control" placeholder="名号或封号(选填)" value="{{ member.name_title if member and member.name_title else '' }}">
+                        </div>
                     </div>
                     </div>
 
 
                     <div class="section-title">状态信息</div>
                     <div class="section-title">状态信息</div>
@@ -349,22 +365,6 @@
                             
                             
                             <div class="section-title mt-0">谱系详情</div>
                             <div class="section-title mt-0">谱系详情</div>
                             <div class="row g-3 mb-4">
                             <div class="row g-3 mb-4">
-                                <div class="col-md-4">
-                                    <label class="form-label">曾用名</label>
-                                    <input type="text" name="former_name" class="form-control" value="{{ member.former_name if member else '' }}">
-                                </div>
-                                <div class="col-md-4">
-                                    <label class="form-label">幼名/乳名</label>
-                                    <input type="text" name="childhood_name" class="form-control" value="{{ member.childhood_name if member else '' }}">
-                                </div>
-                                <div class="col-md-4">
-                                    <label class="form-label">字辈</label>
-                                    <input type="text" name="name_word" class="form-control" value="{{ member.name_word if member else '' }}">
-                                </div>
-                                <div class="col-md-6">
-                                    <label class="form-label">名号/封号</label>
-                                    <input type="text" name="name_title" class="form-control" value="{{ member.name_title if member else '' }}">
-                                </div>
                                 <div class="col-md-6">
                                 <div class="col-md-6">
                                     <label class="form-label">分房/堂号</label>
                                     <label class="form-label">分房/堂号</label>
                                     <input type="text" name="branch_family_hall" class="form-control" value="{{ member.branch_family_hall if member else '' }}">
                                     <input type="text" name="branch_family_hall" class="form-control" value="{{ member.branch_family_hall if member else '' }}">

+ 84 - 8
templates/lineage_query.html

@@ -250,7 +250,44 @@
         color: rgba(255,255,255,0.8);
         color: rgba(255,255,255,0.8);
         font-weight: 500;
         font-weight: 500;
     }
     }
-    
+
+    /* 曾用名 / 幼名 副标签 */
+    .node-alt-names {
+        display: flex;
+        flex-wrap: wrap;
+        gap: 3px;
+        justify-content: center;
+        margin-top: 4px;
+    }
+    .node-alt-badge {
+        display: inline-block;
+        font-size: 10px;
+        line-height: 1.3;
+        padding: 1px 5px;
+        border-radius: 3px;
+        white-space: nowrap;
+        max-width: 90px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+    }
+    .node-alt-badge.former {
+        background: rgba(251,191,36,0.22);
+        color: #fde68a;
+        border: 1px solid rgba(251,191,36,0.35);
+    }
+    .node-alt-badge.childhood {
+        background: rgba(52,211,153,0.18);
+        color: #6ee7b7;
+        border: 1px solid rgba(52,211,153,0.30);
+    }
+    /* 在 center / direct-ancestor 节点上稍微大一点 */
+    .tree-node.center .node-alt-badge,
+    .tree-node.direct-ancestor .node-alt-badge {
+        font-size: 11px;
+        padding: 2px 6px;
+        max-width: 110px;
+    }
+
     /* Connection lines */
     /* Connection lines */
     .connection-line {
     .connection-line {
         width: 4px;
         width: 4px;
@@ -488,8 +525,17 @@
                     <!-- 搜索框 -->
                     <!-- 搜索框 -->
                     <div class="search-box">
                     <div class="search-box">
                         <div class="input-group">
                         <div class="input-group">
-                            <input type="text" id="searchInput" class="form-control" placeholder="搜索成员姓名(支持简繁)" />
-                            <button class="btn btn-primary" onclick="searchMember()">
+                            <select id="searchType" class="form-select form-select-sm"
+                                    style="max-width:110px;flex-shrink:0;border-right:none;border-radius:6px 0 0 6px;font-size:13px;">
+                                <option value="name">成员姓名</option>
+                                <option value="former_name">曾用名</option>
+                                <option value="childhood_name">幼名/乳名</option>
+                                <option value="name_word">字辈</option>
+                            </select>
+                            <input type="text" id="searchInput" class="form-control"
+                                   placeholder="搜索成员…" style="border-radius:0;font-size:13px;" />
+                            <button class="btn btn-primary" onclick="searchMember()"
+                                    style="border-radius:0 6px 6px 0;">
                                 <i class="bi bi-search"></i>
                                 <i class="bi bi-search"></i>
                             </button>
                             </button>
                         </div>
                         </div>
@@ -529,23 +575,24 @@
 <script>
 <script>
 // Search member
 // Search member
 async function searchMember() {
 async function searchMember() {
-    const keyword = document.getElementById('searchInput').value.trim();
+    const keyword    = document.getElementById('searchInput').value.trim();
+    const searchType = (document.getElementById('searchType') || {}).value || 'name';
     if (!keyword) {
     if (!keyword) {
         alert('请输入搜索关键词');
         alert('请输入搜索关键词');
         return;
         return;
     }
     }
-    
+
     // Show loading state
     // Show loading state
     const searchBtn = document.querySelector('.search-box button');
     const searchBtn = document.querySelector('.search-box button');
     const originalBtnHtml = searchBtn.innerHTML;
     const originalBtnHtml = searchBtn.innerHTML;
     searchBtn.disabled = true;
     searchBtn.disabled = true;
     searchBtn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>';
     searchBtn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>';
-    
+
     try {
     try {
         const response = await fetch('/manager/api/search_member', {
         const response = await fetch('/manager/api/search_member', {
             method: 'POST',
             method: 'POST',
             headers: { 'Content-Type': 'application/json' },
             headers: { 'Content-Type': 'application/json' },
-            body: JSON.stringify({ keyword: keyword }),
+            body: JSON.stringify({ keyword: keyword, search_type: searchType }),
             credentials: 'include'
             credentials: 'include'
         });
         });
         
         
@@ -590,6 +637,11 @@ function showMemberSelection(members) {
         const fatherPart = member.father_name
         const fatherPart = member.father_name
             ? `<span style="color: rgba(255,255,255,0.5); font-size: 12px; margin-left: 6px;">父: ${member.father_name}${member.father_simplified_name && member.father_simplified_name !== member.father_name ? '(' + member.father_simplified_name + ')' : ''}</span>` : '';
             ? `<span style="color: rgba(255,255,255,0.5); font-size: 12px; margin-left: 6px;">父: ${member.father_name}${member.father_simplified_name && member.father_simplified_name !== member.father_name ? '(' + member.father_simplified_name + ')' : ''}</span>` : '';
         const idPart = `<span style="color: rgba(255,200,100,0.6); font-size: 11px; margin-left: 6px;">ID:${member.id}</span>`;
         const idPart = `<span style="color: rgba(255,200,100,0.6); font-size: 11px; margin-left: 6px;">ID:${member.id}</span>`;
+        // 曾用名 / 幼名 小标签
+        const altBadges = [];
+        if (member.former_name)    altBadges.push(`<span style="display:inline-block;background:rgba(251,191,36,0.18);border:1px solid rgba(251,191,36,0.35);color:#fde68a;font-size:11px;border-radius:3px;padding:1px 6px;margin-left:4px;">曾:${member.former_name}</span>`);
+        if (member.childhood_name) altBadges.push(`<span style="display:inline-block;background:rgba(52,211,153,0.15);border:1px solid rgba(52,211,153,0.30);color:#6ee7b7;font-size:11px;border-radius:3px;padding:1px 6px;margin-left:4px;">幼:${member.childhood_name}</span>`);
+        const altBadgeHtml = altBadges.length ? altBadges.join('') : '';
         const adoptionPart = member.adoption_note
         const adoptionPart = member.adoption_note
             ? `<div style="margin-top: 3px; margin-left: 2px;">
             ? `<div style="margin-top: 3px; margin-left: 2px;">
                    <span style="display:inline-block; background: rgba(220,80,30,0.18); border: 1px solid rgba(220,100,30,0.45);
                    <span style="display:inline-block; background: rgba(220,80,30,0.18); border: 1px solid rgba(220,100,30,0.45);
@@ -629,7 +681,7 @@ function showMemberSelection(members) {
                     <div>
                     <div>
                         <span style="color: #ffd700; font-size: 13px; margin-right: 8px; flex-shrink: 0;">${index + 1}.</span>
                         <span style="color: #ffd700; font-size: 13px; margin-right: 8px; flex-shrink: 0;">${index + 1}.</span>
                         <span style="color: #fff; font-weight: 600;">${member.name}</span>
                         <span style="color: #fff; font-weight: 600;">${member.name}</span>
-                        ${simplifiedPart}${genPart}${fatherPart}${idPart}
+                        ${simplifiedPart}${genPart}${fatherPart}${idPart}${altBadgeHtml}
                     </div>
                     </div>
                     ${adoptionPart}${childrenPart}
                     ${adoptionPart}${childrenPart}
                 </div>
                 </div>
@@ -830,6 +882,13 @@ function renderNode(person, type) {
         adoptLabel = `<div class="adoption-label adopted-in-label">${adoptText}</div>`;
         adoptLabel = `<div class="adoption-label adopted-in-label">${adoptText}</div>`;
     }
     }
 
 
+    // 曾用名 / 幼名 / 乳名 副标签
+    let altNameHtml = '';
+    const altParts = [];
+    if (person.former_name)    altParts.push(`<span class="node-alt-badge former">曾:${person.former_name}</span>`);
+    if (person.childhood_name) altParts.push(`<span class="node-alt-badge childhood">幼:${person.childhood_name}</span>`);
+    if (altParts.length) altNameHtml = `<div class="node-alt-names">${altParts.join('')}</div>`;
+
     return `
     return `
         <div class="${cls}" data-id="${person.id}" onclick="openPersonDetail(${person.id})">
         <div class="${cls}" data-id="${person.id}" onclick="openPersonDetail(${person.id})">
             <div class="node-name">${person.name}</div>
             <div class="node-name">${person.name}</div>
@@ -838,6 +897,7 @@ function renderNode(person, type) {
             <div class="node-info">
             <div class="node-info">
                 ${person.name_word ? person.name_word + ' · ' : ''}${person.name_word_generation || ''}
                 ${person.name_word ? person.name_word + ' · ' : ''}${person.name_word_generation || ''}
             </div>
             </div>
+            ${altNameHtml}
             ${adoptLabel}
             ${adoptLabel}
         </div>`;
         </div>`;
 }
 }
@@ -1219,5 +1279,21 @@ document.getElementById('searchInput').addEventListener('keypress', function(e)
         searchMember();
         searchMember();
     }
     }
 });
 });
+
+// 根据搜索类型动态更新 placeholder
+const _searchTypeEl = document.getElementById('searchType');
+const _searchInputEl = document.getElementById('searchInput');
+const _placeholderMap = {
+    name:           '搜索成员姓名(支持简繁)',
+    former_name:    '搜索曾用名…',
+    childhood_name: '搜索幼名 / 乳名…',
+    name_word:      '搜索字辈…',
+};
+if (_searchTypeEl && _searchInputEl) {
+    _searchTypeEl.addEventListener('change', function() {
+        _searchInputEl.placeholder = _placeholderMap[this.value] || '搜索成员…';
+        _searchInputEl.focus();
+    });
+}
 </script>
 </script>
 {% endblock %}
 {% endblock %}