diff --git a/fam-core/src/fam_core/db_layer.py b/fam-core/src/fam_core/db_layer.py index 4739b02..e2c3221 100644 --- a/fam-core/src/fam_core/db_layer.py +++ b/fam-core/src/fam_core/db_layer.py @@ -106,31 +106,35 @@ def get_sync_videos(limit=15, offset=0, date_filter=None) -> List[Dict]: 排序/日期维度按视频实际录制时间(event_start_time,文件名解析), 为空回退 processed_at/updated_at/created_at。 date_filter 形如 '2026-08-21'。 + 只返回"有内容"的会话:运动片段(filename 前缀 motion_)或含事件的视频; + 整段素材分割 0 段的空会话(历史素材无运动事件)不展示,避免淹没时间轴。 """ conn = get_conn() try: cur = conn.cursor(pymysql.cursors.DictCursor) # 录制时间优先,回退分析时间 date_expr = "COALESCE(NULLIF(event_start_time,''), processed_at, updated_at, created_at)" + content_filter = ("v.filename LIKE 'motion_%' " + "OR EXISTS(SELECT 1 FROM sync_events se WHERE se.video_id = v.id)") if date_filter: cur.execute( - f"""SELECT id, filename, camera_name, event_start_time, status, - summary_json, events_json, people_json, compute_provider, - processed_at, updated_at, - (SELECT COUNT(*) FROM sync_events se WHERE se.video_id = sync_videos.id) AS event_count - FROM sync_videos - WHERE status='done' AND {date_expr} LIKE %s + f"""SELECT v.id, v.filename, v.camera_name, v.event_start_time, v.status, + v.summary_json, v.events_json, v.people_json, v.compute_provider, + v.processed_at, v.updated_at, + (SELECT COUNT(*) FROM sync_events se WHERE se.video_id = v.id) AS event_count + FROM sync_videos v + WHERE v.status='done' AND ({content_filter}) AND {date_expr} LIKE %s ORDER BY {date_expr} DESC LIMIT %s OFFSET %s""", (f'{date_filter}%', limit, offset)) else: cur.execute( - f"""SELECT id, filename, camera_name, event_start_time, status, - summary_json, events_json, people_json, compute_provider, - processed_at, updated_at, - (SELECT COUNT(*) FROM sync_events se WHERE se.video_id = sync_videos.id) AS event_count - FROM sync_videos - WHERE status='done' + f"""SELECT v.id, v.filename, v.camera_name, v.event_start_time, v.status, + v.summary_json, v.events_json, v.people_json, v.compute_provider, + v.processed_at, v.updated_at, + (SELECT COUNT(*) FROM sync_events se WHERE se.video_id = v.id) AS event_count + FROM sync_videos v + WHERE v.status='done' AND ({content_filter}) ORDER BY {date_expr} DESC LIMIT %s OFFSET %s""", (limit, offset)) @@ -524,19 +528,25 @@ def get_sync_stats(date_str: str = None) -> Dict: if date_str: cur.execute( """SELECT - COUNT(*) AS videos, + (SELECT COUNT(*) FROM sync_videos sv + WHERE sv.status='done' + AND (sv.filename LIKE 'motion_%' + OR EXISTS(SELECT 1 FROM sync_events se WHERE se.video_id=sv.id)) + AND {d} LIKE %s) AS videos, (SELECT COUNT(*) FROM sync_events se JOIN sync_videos sv ON se.video_id=sv.id WHERE {d} LIKE %s) AS events, (SELECT COALESCE(SUM(se.is_attention_event),0) FROM sync_events se JOIN sync_videos sv ON se.video_id=sv.id - WHERE {d} LIKE %s) AS attention - FROM sync_videos sv WHERE {d} LIKE %s""".format(d=_D), + WHERE {d} LIKE %s) AS attention""".format(d=_D), (f'{date_str}%', f'{date_str}%', f'{date_str}%')) else: cur.execute( """SELECT - (SELECT COUNT(*) FROM sync_videos WHERE status='done') AS videos, + (SELECT COUNT(*) FROM sync_videos + WHERE status='done' + AND (filename LIKE 'motion_%' + OR EXISTS(SELECT 1 FROM sync_events se WHERE se.video_id=sync_videos.id))) AS videos, (SELECT COUNT(*) FROM sync_events) AS events, (SELECT COALESCE(SUM(is_attention_event),0) FROM sync_events) AS attention""") stat = cur.fetchone() or {}