林海 1 day ago
parent
commit
5f738a45db
2 changed files with 90 additions and 18 deletions
  1. 84 15
      app.py
  2. 6 3
      templates/lineage_query.html

+ 84 - 15
app.py

@@ -1902,8 +1902,18 @@ def get_lineage(member_id):
                     co_row = cursor.fetchone()
                     co_row = cursor.fetchone()
                     parent['child_order'] = co_row['child_order'] if co_row else None
                     parent['child_order'] = co_row['child_order'] if co_row else None
 
 
-                    # 获取祖先的兄弟(含 child_order 和 sub_relation_type,用于出继/入继标注)
-                    cursor.execute("""
+                    # 获取祖先的兄弟(按模式过滤 + 出继/入继标注)
+                    if mode == 'blood':
+                        anc_sib_filter = "AND COALESCE(r.sub_relation_type, 0) != 3"
+                    else:
+                        anc_sib_filter = """AND (
+                            COALESCE(r.sub_relation_type, 0) != 2
+                            OR NOT EXISTS (
+                                SELECT 1 FROM family_relation_info r2
+                                WHERE r2.child_mid = c.id AND r2.sub_relation_type = 3
+                            )
+                        )"""
+                    cursor.execute(f"""
                         SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation, c.former_name, c.childhood_name,
                         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,
@@ -1911,11 +1921,12 @@ def get_lineage(member_id):
                         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
                         WHERE r.parent_mid = %s AND r.relation_type IN (1, 2) AND c.id != %s
                         WHERE r.parent_mid = %s AND r.relation_type IN (1, 2) AND c.id != %s
+                          {anc_sib_filter}
                         ORDER BY COALESCE(r.child_order, 99999), c.id
                         ORDER BY COALESCE(r.child_order, 99999), c.id
                         LIMIT 30
                         LIMIT 30
                     """, (grandparent['id'], parent['id']))
                     """, (grandparent['id'], parent['id']))
                     parent_siblings = cursor.fetchall()
                     parent_siblings = cursor.fetchall()
-                    # 为入继兄弟补充"出继自xx"标注
+                    # 为入继兄弟补充"出继自xx,入继至yy"标注
                     for sib in parent_siblings:
                     for sib in parent_siblings:
                         if sib.get('sub_relation_type') == 3:
                         if sib.get('sub_relation_type') == 3:
                             cursor.execute("""
                             cursor.execute("""
@@ -2051,7 +2062,18 @@ def get_lineage(member_id):
                 co_row = cursor.fetchone()
                 co_row = cursor.fetchone()
                 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("""
+                # 香火模式:排除已出继的兄弟(已被别家收入的);血脉模式:排除从外面入继进来的
+                if mode == 'blood':
+                    sib_filter = "AND COALESCE(r.sub_relation_type, 0) != 3"
+                else:
+                    sib_filter = """AND (
+                        COALESCE(r.sub_relation_type, 0) != 2
+                        OR NOT EXISTS (
+                            SELECT 1 FROM family_relation_info r2
+                            WHERE r2.child_mid = c.id AND r2.sub_relation_type = 3
+                        )
+                    )"""
+                cursor.execute(f"""
                     SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation, c.former_name, c.childhood_name,
                     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,
@@ -2059,6 +2081,7 @@ def get_lineage(member_id):
                     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
                     WHERE r.parent_mid = %s AND r.relation_type IN (1, 2) AND c.id != %s
                     WHERE r.parent_mid = %s AND r.relation_type IN (1, 2) AND c.id != %s
+                      {sib_filter}
                     ORDER BY COALESCE(r.child_order, 99999), c.id
                     ORDER BY COALESCE(r.child_order, 99999), c.id
                     LIMIT 30
                     LIMIT 30
                 """, (parent_id, member_id))
                 """, (parent_id, member_id))
@@ -2242,7 +2265,17 @@ def get_ancestors_above(ancestor_id):
                     co_row = cursor.fetchone()
                     co_row = cursor.fetchone()
                     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("""
+                    if mode == 'blood':
+                        ab_sib_filter = "AND COALESCE(r.sub_relation_type, 0) != 3"
+                    else:
+                        ab_sib_filter = """AND (
+                            COALESCE(r.sub_relation_type, 0) != 2
+                            OR NOT EXISTS (
+                                SELECT 1 FROM family_relation_info r2
+                                WHERE r2.child_mid = c.id AND r2.sub_relation_type = 3
+                            )
+                        )"""
+                    cursor.execute(f"""
                         SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation, c.former_name, c.childhood_name,
                         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,
@@ -2250,6 +2283,7 @@ def get_ancestors_above(ancestor_id):
                         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
                         WHERE r.parent_mid = %s AND r.relation_type IN (1,2) AND c.id != %s
                         WHERE r.parent_mid = %s AND r.relation_type IN (1,2) AND c.id != %s
+                          {ab_sib_filter}
                         ORDER BY COALESCE(r.child_order, 1), c.id
                         ORDER BY COALESCE(r.child_order, 1), c.id
                         LIMIT 10
                         LIMIT 10
                     """, (grandparent['id'], parent['id']))
                     """, (grandparent['id'], parent['id']))
@@ -2298,13 +2332,23 @@ def get_descendants(parent_id):
     if 'user_id' not in session:
     if 'user_id' not in session:
         return jsonify({"success": False, "message": "Unauthorized"}), 401
         return jsonify({"success": False, "message": "Unauthorized"}), 401
     
     
-    # Get excluded IDs from query parameter
     excluded_ids = request.args.get('exclude', '')
     excluded_ids = request.args.get('exclude', '')
-    excluded_list = []
-    if excluded_ids:
-        excluded_list = [int(id.strip()) for id in excluded_ids.split(',') if id.strip().isdigit()]
-    
-    print(f"[get_descendants] Parent ID: {parent_id}, Excluded IDs: {excluded_list}")
+    excluded_list = [int(i.strip()) for i in excluded_ids.split(',') if i.strip().isdigit()]
+    mode = request.args.get('mode', 'incense')
+
+    # 按模式决定子女过滤策略(与 get_lineage 保持一致)
+    if mode == 'blood':
+        mode_filter = "AND COALESCE(r.sub_relation_type, 0) != 3"
+    else:  # incense
+        mode_filter = """AND (
+            COALESCE(r.sub_relation_type, 0) != 2
+            OR NOT EXISTS (
+                SELECT 1 FROM family_relation_info r2
+                WHERE r2.child_mid = c.id AND r2.sub_relation_type = 3
+            )
+        )"""
+
+    print(f"[get_descendants] Parent ID: {parent_id}, mode={mode}, Excluded IDs: {excluded_list}")
     
     
     conn = get_db_connection()
     conn = get_db_connection()
     try:
     try:
@@ -2328,12 +2372,14 @@ def get_descendants(parent_id):
                                   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
                     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
-                    WHERE r.parent_mid = %s AND r.relation_type IN (1, 2) AND c.id NOT IN ({placeholders})
+                    WHERE r.parent_mid = %s AND r.relation_type IN (1, 2)
+                      AND c.id NOT IN ({placeholders})
+                      {mode_filter}
                     ORDER BY COALESCE(r.child_order, 99999), c.id
                     ORDER BY COALESCE(r.child_order, 99999), c.id
                     LIMIT 20
                     LIMIT 20
                 """, (parent_id,) + tuple(excluded_list))
                 """, (parent_id,) + tuple(excluded_list))
             else:
             else:
-                cursor.execute("""
+                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,
                            c.former_name, c.childhood_name,
                            r.sub_relation_type,
                            r.sub_relation_type,
@@ -2343,6 +2389,7 @@ def get_descendants(parent_id):
                     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
                     WHERE r.parent_mid = %s AND r.relation_type IN (1, 2)
                     WHERE r.parent_mid = %s AND r.relation_type IN (1, 2)
+                      {mode_filter}
                     ORDER BY COALESCE(r.child_order, 99999), c.id
                     ORDER BY COALESCE(r.child_order, 99999), c.id
                     LIMIT 20
                     LIMIT 20
                 """, (parent_id,))
                 """, (parent_id,))
@@ -6242,7 +6289,17 @@ def api_get_lineage(member_id):
                     co_row = cursor.fetchone()
                     co_row = cursor.fetchone()
                     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("""
+                    if mode == 'blood':
+                        _sib_filter = "AND COALESCE(r.sub_relation_type, 0) != 3"
+                    else:
+                        _sib_filter = """AND (
+                            COALESCE(r.sub_relation_type, 0) != 2
+                            OR NOT EXISTS (
+                                SELECT 1 FROM family_relation_info r2
+                                WHERE r2.child_mid = c.id AND r2.sub_relation_type = 3
+                            )
+                        )"""
+                    cursor.execute(f"""
                         SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation, c.former_name, c.childhood_name,
                         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,
@@ -6250,6 +6307,7 @@ def api_get_lineage(member_id):
                         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
                         WHERE r.parent_mid = %s AND r.relation_type IN (1,2) AND c.id != %s
                         WHERE r.parent_mid = %s AND r.relation_type IN (1,2) AND c.id != %s
+                          {{_sib_filter}}
                         ORDER BY COALESCE(r.child_order, 1), c.id
                         ORDER BY COALESCE(r.child_order, 1), c.id
                         LIMIT 10
                         LIMIT 10
                     """, (grandparent['id'], parent['id']))
                     """, (grandparent['id'], parent['id']))
@@ -6486,7 +6544,17 @@ def api_get_ancestors_above(ancestor_id):
                     co_row = cursor.fetchone()
                     co_row = cursor.fetchone()
                     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("""
+                    if mode == 'blood':
+                        _sib_filter = "AND COALESCE(r.sub_relation_type, 0) != 3"
+                    else:
+                        _sib_filter = """AND (
+                            COALESCE(r.sub_relation_type, 0) != 2
+                            OR NOT EXISTS (
+                                SELECT 1 FROM family_relation_info r2
+                                WHERE r2.child_mid = c.id AND r2.sub_relation_type = 3
+                            )
+                        )"""
+                    cursor.execute(f"""
                         SELECT c.id, c.name, c.simplified_name, c.name_word, c.name_word_generation, c.former_name, c.childhood_name,
                         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,
@@ -6494,6 +6562,7 @@ def api_get_ancestors_above(ancestor_id):
                         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
                         WHERE r.parent_mid = %s AND r.relation_type IN (1,2) AND c.id != %s
                         WHERE r.parent_mid = %s AND r.relation_type IN (1,2) AND c.id != %s
+                          {{_sib_filter}}
                         ORDER BY COALESCE(r.child_order, 1), c.id
                         ORDER BY COALESCE(r.child_order, 1), c.id
                         LIMIT 10
                         LIMIT 10
                     """, (grandparent['id'], parent['id']))
                     """, (grandparent['id'], parent['id']))

+ 6 - 3
templates/lineage_query.html

@@ -1228,10 +1228,13 @@ async function toggleChildren(btn, parentId) {
             
             
             // Get already displayed descendant IDs to exclude
             // Get already displayed descendant IDs to exclude
             const excludedIds = getExcludedDescendantIds(btn);
             const excludedIds = getExcludedDescendantIds(btn);
-            const excludeParam = excludedIds.length > 0 ? `?exclude=${excludedIds.join(',')}` : '';
-            
+            const modeParam = `mode=${_lineageMode || 'incense'}`;
+            const excludeParam = excludedIds.length > 0
+                ? `?${modeParam}&exclude=${excludedIds.join(',')}`
+                : `?${modeParam}`;
+
             console.log(`[ToggleChildren] Parent ID: ${parentId}, Excluded IDs: ${excludedIds}, URL: /manager/api/get_descendants/${parentId}${excludeParam}`);
             console.log(`[ToggleChildren] Parent ID: ${parentId}, Excluded IDs: ${excludedIds}, URL: /manager/api/get_descendants/${parentId}${excludeParam}`);
-            
+
             try {
             try {
                 const response = await fetch(`/manager/api/get_descendants/${parentId}${excludeParam}`, {
                 const response = await fetch(`/manager/api/get_descendants/${parentId}${excludeParam}`, {
                     credentials: 'include'
                     credentials: 'include'