""" 数据库管理模块 """ import sqlite3 import datetime from pathlib import Path from config import DB_PATH, DB_SCHEMA class Database: """SQLite 数据库管理""" def __init__(self): self.db_path = DB_PATH self._init_db() def _init_db(self): """初始化数据库""" conn = sqlite3.connect(self.db_path) conn.executescript(DB_SCHEMA) conn.commit() conn.close() def _get_conn(self): """获取数据库连接""" return sqlite3.connect(self.db_path) def add_image(self, path, camera_id=0): """添加图片记录 Returns: int: 图片ID """ conn = self._get_conn() cursor = conn.cursor() cursor.execute( "INSERT INTO images (path, camera_id, timestamp) VALUES (?, ?, ?)", (path, camera_id, datetime.datetime.now().isoformat()) ) image_id = cursor.lastrowid conn.commit() conn.close() return image_id def mark_image_analyzed(self, image_id): """标记图片已分析""" conn = self._get_conn() conn.execute("UPDATE images SET analyzed = 1 WHERE id = ?", (image_id,)) conn.commit() conn.close() def add_event(self, image_id, event_type, description, confidence): """添加事件记录""" conn = self._get_conn() conn.execute( "INSERT INTO events (image_id, event_type, description, confidence, timestamp) VALUES (?, ?, ?, ?, ?)", (image_id, event_type, description, confidence, datetime.datetime.now().isoformat()) ) conn.commit() conn.close() def get_images(self, limit=50, offset=0, analyzed_only=False): """获取图片列表""" conn = self._get_conn() conn.row_factory = sqlite3.Row if analyzed_only: cursor = conn.execute( "SELECT * FROM images WHERE analyzed = 1 ORDER BY timestamp DESC LIMIT ? OFFSET ?", (limit, offset) ) else: cursor = conn.execute( "SELECT * FROM images ORDER BY timestamp DESC LIMIT ? OFFSET ?", (limit, offset) ) rows = cursor.fetchall() conn.close() return [dict(row) for row in rows] def get_events(self, limit=50, offset=0, event_type=None): """获取事件列表""" conn = self._get_conn() conn.row_factory = sqlite3.Row if event_type: cursor = conn.execute( """SELECT e.*, i.path as image_path, i.timestamp as image_timestamp FROM events e JOIN images i ON e.image_id = i.id WHERE e.event_type = ? ORDER BY e.timestamp DESC LIMIT ? OFFSET ?""", (event_type, limit, offset) ) else: cursor = conn.execute( """SELECT e.*, i.path as image_path, i.timestamp as image_timestamp FROM events e JOIN images i ON e.image_id = i.id ORDER BY e.timestamp DESC LIMIT ? OFFSET ?""", (limit, offset) ) rows = cursor.fetchall() conn.close() return [dict(row) for row in rows] def get_image_by_id(self, image_id): """获取单个图片""" conn = self._get_conn() conn.row_factory = sqlite3.Row cursor = conn.execute("SELECT * FROM images WHERE id = ?", (image_id,)) row = cursor.fetchone() conn.close() return dict(row) if row else None def get_events_by_image(self, image_id): """获取图片相关的事件""" conn = self._get_conn() conn.row_factory = sqlite3.Row cursor = conn.execute( "SELECT * FROM events WHERE image_id = ? ORDER BY timestamp DESC", (image_id,) ) rows = cursor.fetchall() conn.close() return [dict(row) for row in rows] def get_stats(self): """获取统计信息""" conn = self._get_conn() # 图片统计 total_images = conn.execute("SELECT COUNT(*) FROM images").fetchone()[0] analyzed_images = conn.execute("SELECT COUNT(*) FROM images WHERE analyzed = 1").fetchone()[0] # 事件统计 total_events = conn.execute("SELECT COUNT(*) FROM events").fetchone()[0] # 事件类型统计 cursor = conn.execute( "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type ORDER BY count DESC" ) event_types = [{'type': row[0], 'count': row[1]} for row in cursor.fetchall()] conn.close() return { 'total_images': total_images, 'analyzed_images': analyzed_images, 'unanalyzed_images': total_images - analyzed_images, 'total_events': total_events, 'event_types': event_types } def delete_image(self, image_id): """删除图片和相关事件""" conn = self._get_conn() # 获取图片路径 cursor = conn.execute("SELECT path FROM images WHERE id = ?", (image_id,)) row = cursor.fetchone() if row: image_path = row[0] # 删除事件 conn.execute("DELETE FROM events WHERE image_id = ?", (image_id,)) # 删除图片记录 conn.execute("DELETE FROM images WHERE id = ?", (image_id,)) conn.commit() conn.close() # 删除实际文件 try: Path(image_path).unlink(missing_ok=True) except: pass return True conn.close() return False def get_unanalyzed_images(self, limit=10): """获取未分析的图片""" conn = self._get_conn() conn.row_factory = sqlite3.Row cursor = conn.execute( "SELECT * FROM images WHERE analyzed = 0 ORDER BY timestamp ASC LIMIT ?", (limit,) ) rows = cursor.fetchall() conn.close() return [dict(row) for row in rows] # 全局实例 db = Database()