BodyBalanceEvaluation/backend/database.py

955 lines
34 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
数据库管理模块
负责SQLite数据库的创建、连接和数据操作
"""
import sqlite3
import json
import uuid
from datetime import datetime
from typing import List, Dict, Optional, Any
import logging
logger = logging.getLogger(__name__)
class DatabaseManager:
"""数据库管理器"""
def __init__(self, db_path: str):
self.db_path = db_path
self.connection = None
def get_connection(self) -> sqlite3.Connection:
"""获取数据库连接"""
if not self.connection:
self.connection = sqlite3.connect(
self.db_path,
check_same_thread=False,
timeout=30.0
)
self.connection.row_factory = sqlite3.Row
return self.connection
def init_database(self):
"""初始化数据库表结构"""
conn = self.get_connection()
cursor = conn.cursor()
try:
# 创建患者表
cursor.execute('''
CREATE TABLE IF NOT EXISTS patients (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
gender TEXT,
age INTEGER,
birth_date TIMESTAMP,
nationality TEXT,
height REAL,
weight REAL,
phone TEXT,
shoe_size TEXT,
medical_history TEXT,
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
# 创建检测会话表
cursor.execute('''
CREATE TABLE IF NOT EXISTS detection_sessions (
id TEXT PRIMARY KEY,
patient_id TEXT NOT NULL,
start_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
end_time TIMESTAMP,
duration INTEGER,
frequency INTEGER,
status TEXT DEFAULT 'created',
settings TEXT,
data_points INTEGER DEFAULT 0,
video_path TEXT,
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (patient_id) REFERENCES patients (id)
)
''')
# 创建检测数据表
cursor.execute('''
CREATE TABLE IF NOT EXISTS detection_data (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
data_type TEXT NOT NULL,
data_value TEXT NOT NULL,
FOREIGN KEY (session_id) REFERENCES detection_sessions (id)
)
''')
# 创建分析结果表
cursor.execute('''
CREATE TABLE IF NOT EXISTS analysis_results (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL,
analysis_type TEXT NOT NULL,
result_data TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (session_id) REFERENCES detection_sessions (id)
)
''')
# 创建系统设置表
cursor.execute('''
CREATE TABLE IF NOT EXISTS system_settings (
key TEXT PRIMARY KEY,
value TEXT NOT NULL,
description TEXT,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
# 创建用户表
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
username TEXT UNIQUE NOT NULL,
password TEXT NOT NULL,
register_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
is_active BOOLEAN DEFAULT 0,
user_type TEXT DEFAULT 'user',
phone TEXT DEFAULT '',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
# 创建索引
cursor.execute('CREATE INDEX IF NOT EXISTS idx_patients_name ON patients (name)')
cursor.execute('CREATE INDEX IF NOT EXISTS idx_sessions_patient ON detection_sessions (patient_id)')
cursor.execute('CREATE INDEX IF NOT EXISTS idx_sessions_time ON detection_sessions (start_time)')
cursor.execute('CREATE INDEX IF NOT EXISTS idx_data_session ON detection_data (session_id)')
cursor.execute('CREATE INDEX IF NOT EXISTS idx_data_timestamp ON detection_data (timestamp)')
cursor.execute('CREATE INDEX IF NOT EXISTS idx_users_username ON users (username)')
cursor.execute('CREATE INDEX IF NOT EXISTS idx_users_type ON users (user_type)')
cursor.execute('CREATE INDEX IF NOT EXISTS idx_users_phone ON users (phone)')
# 插入默认管理员账户(如果不存在)
cursor.execute('SELECT COUNT(*) FROM users WHERE username = ?', ('admin',))
admin_exists = cursor.fetchone()[0]
if admin_exists == 0:
import hashlib
admin_id = str(uuid.uuid4())
# 默认密码为 admin123使用MD5加密
admin_password = hashlib.md5('admin123'.encode()).hexdigest()
cursor.execute('''
INSERT INTO users (id, name, username, password, is_active, user_type)
VALUES (?, ?, ?, ?, ?, ?)
''', (admin_id, '系统管理员', 'admin', admin_password, 1, 'admin'))
logger.info('创建默认管理员账户: admin/admin123')
conn.commit()
logger.info('数据库初始化完成')
except Exception as e:
conn.rollback()
logger.error(f'数据库初始化失败: {e}')
raise
# ==================== 患者管理 ====================
def create_patient(self, patient_data: Dict[str, Any]) -> str:
"""创建患者记录"""
conn = self.get_connection()
cursor = conn.cursor()
try:
patient_id = str(uuid.uuid4())
cursor.execute('''
INSERT INTO patients (
id, name, gender, age, birth_date, height, weight,
phone, shoe_size, medical_history, notes
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (
patient_id,
patient_data.get('name'),
patient_data.get('gender'),
patient_data.get('age'),
patient_data.get('birth_date'),
patient_data.get('height'),
patient_data.get('weight'),
patient_data.get('phone'),
patient_data.get('shoe_size'),
patient_data.get('medical_history'),
patient_data.get('notes')
))
conn.commit()
logger.info(f'创建患者记录: {patient_id}')
return patient_id
except Exception as e:
conn.rollback()
logger.error(f'创建患者记录失败: {e}')
raise
def get_patients(self, page: int = 1, size: int = 10, keyword: str = '') -> List[Dict]:
"""获取患者列表"""
conn = self.get_connection()
cursor = conn.cursor()
try:
offset = (page - 1) * size
if keyword:
cursor.execute('''
SELECT * FROM patients
WHERE name LIKE ? OR phone LIKE ?
ORDER BY created_at DESC
LIMIT ? OFFSET ?
''', (f'%{keyword}%', f'%{keyword}%', size, offset))
else:
cursor.execute('''
SELECT * FROM patients
ORDER BY created_at DESC
LIMIT ? OFFSET ?
''', (size, offset))
rows = cursor.fetchall()
return [dict(row) for row in rows]
except Exception as e:
logger.error(f'获取患者列表失败: {e}')
raise
def get_patients_count(self, keyword: str = '') -> int:
"""获取患者总数"""
conn = self.get_connection()
cursor = conn.cursor()
try:
if keyword:
cursor.execute('''
SELECT COUNT(*) FROM patients
WHERE name LIKE ? OR phone LIKE ?
''', (f'%{keyword}%', f'%{keyword}%'))
else:
cursor.execute('SELECT COUNT(*) FROM patients')
return cursor.fetchone()[0]
except Exception as e:
logger.error(f'获取患者总数失败: {e}')
return 0
def get_patient(self, patient_id: str) -> Optional[Dict]:
"""获取单个患者信息"""
conn = self.get_connection()
cursor = conn.cursor()
try:
cursor.execute('SELECT * FROM patients WHERE id = ?', (patient_id,))
row = cursor.fetchone()
return dict(row) if row else None
except Exception as e:
logger.error(f'获取患者信息失败: {e}')
return None
def update_patient(self, patient_id: str, patient_data: Dict[str, Any]):
"""更新患者信息"""
conn = self.get_connection()
cursor = conn.cursor()
try:
cursor.execute('''
UPDATE patients SET
name = ?, gender = ?, age = ?, birth_date = ?, height = ?, weight = ?,
phone = ?, shoe_size = ?, medical_history = ?, notes = ?,
updated_at = CURRENT_TIMESTAMP
WHERE id = ?
''', (
patient_data.get('name'),
patient_data.get('gender'),
patient_data.get('age'),
patient_data.get('birth_date'),
patient_data.get('height'),
patient_data.get('weight'),
patient_data.get('phone'),
patient_data.get('shoe_size'),
patient_data.get('medical_history'),
patient_data.get('notes'),
patient_id
))
conn.commit()
logger.info(f'更新患者信息: {patient_id}')
except Exception as e:
conn.rollback()
logger.error(f'更新患者信息失败: {e}')
raise
def delete_patient(self, patient_id: str):
"""删除患者记录"""
conn = self.get_connection()
cursor = conn.cursor()
try:
# 删除相关的检测数据
cursor.execute('''
DELETE FROM detection_data
WHERE session_id IN (
SELECT id FROM detection_sessions WHERE patient_id = ?
)
''', (patient_id,))
# 删除相关的分析结果
cursor.execute('''
DELETE FROM analysis_results
WHERE session_id IN (
SELECT id FROM detection_sessions WHERE patient_id = ?
)
''', (patient_id,))
# 删除检测会话
cursor.execute('DELETE FROM detection_sessions WHERE patient_id = ?', (patient_id,))
# 删除患者记录
cursor.execute('DELETE FROM patients WHERE id = ?', (patient_id,))
conn.commit()
logger.info(f'删除患者记录: {patient_id}')
except Exception as e:
conn.rollback()
logger.error(f'删除患者记录失败: {e}')
raise
# ==================== 检测会话管理 ====================
def create_detection_session(self, patient_id: str, settings: Dict[str, Any]) -> str:
"""创建检测会话"""
conn = self.get_connection()
cursor = conn.cursor()
try:
session_id = str(uuid.uuid4())
cursor.execute('''
INSERT INTO detection_sessions (
id, patient_id, duration, frequency, settings, status
) VALUES (?, ?, ?, ?, ?, ?)
''', (
session_id,
patient_id,
settings.get('duration', 60),
settings.get('frequency', 60),
json.dumps(settings),
'created'
))
conn.commit()
logger.info(f'创建检测会话: {session_id}')
return session_id
except Exception as e:
conn.rollback()
logger.error(f'创建检测会话失败: {e}')
raise
def update_session_status(self, session_id: str, status: str, data_points: int = 0):
"""更新会话状态"""
conn = self.get_connection()
cursor = conn.cursor()
try:
if status in ['completed', 'stopped', 'error']:
cursor.execute('''
UPDATE detection_sessions SET
status = ?, data_points = ?, end_time = CURRENT_TIMESTAMP
WHERE id = ?
''', (status, data_points, session_id))
else:
cursor.execute('''
UPDATE detection_sessions SET
status = ?, data_points = ?
WHERE id = ?
''', (status, data_points, session_id))
conn.commit()
logger.info(f'更新会话状态: {session_id} -> {status}')
except Exception as e:
conn.rollback()
logger.error(f'更新会话状态失败: {e}')
raise
def update_session_duration(self, session_id: str, duration: int):
"""更新会话持续时间"""
conn = self.get_connection()
cursor = conn.cursor()
try:
cursor.execute('''
UPDATE detection_sessions SET duration = ?
WHERE id = ?
''', (duration, session_id))
conn.commit()
logger.info(f'更新会话持续时间: {session_id} -> {duration}')
except Exception as e:
conn.rollback()
logger.error(f'更新会话持续时间失败: {e}')
raise
def update_session_video_path(self, session_id: str, video_path: str):
"""更新会话视频路径"""
conn = self.get_connection()
cursor = conn.cursor()
try:
cursor.execute('''
UPDATE detection_sessions SET video_path = ?
WHERE id = ?
''', (video_path, session_id))
conn.commit()
logger.info(f'更新会话视频路径: {session_id} -> {video_path}')
except Exception as e:
conn.rollback()
logger.error(f'更新会话视频路径失败: {e}')
raise
def get_detection_sessions(self, page: int = 1, size: int = 10, patient_id: str = None) -> List[Dict]:
"""获取检测会话列表"""
conn = self.get_connection()
cursor = conn.cursor()
try:
offset = (page - 1) * size
if patient_id:
cursor.execute('''
SELECT s.*, p.name as patient_name
FROM detection_sessions s
LEFT JOIN patients p ON s.patient_id = p.id
WHERE s.patient_id = ?
ORDER BY s.start_time DESC
LIMIT ? OFFSET ?
''', (patient_id, size, offset))
else:
cursor.execute('''
SELECT s.*, p.name as patient_name
FROM detection_sessions s
LEFT JOIN patients p ON s.patient_id = p.id
ORDER BY s.start_time DESC
LIMIT ? OFFSET ?
''', (size, offset))
rows = cursor.fetchall()
sessions = []
for row in rows:
session = dict(row)
# 解析设置JSON
if session['settings']:
try:
session['settings'] = json.loads(session['settings'])
except:
session['settings'] = {}
sessions.append(session)
return sessions
except Exception as e:
logger.error(f'获取检测会话列表失败: {e}')
raise
def get_sessions_count(self, patient_id: str = None) -> int:
"""获取会话总数"""
conn = self.get_connection()
cursor = conn.cursor()
try:
if patient_id:
cursor.execute('SELECT COUNT(*) FROM detection_sessions WHERE patient_id = ?', (patient_id,))
else:
cursor.execute('SELECT COUNT(*) FROM detection_sessions')
return cursor.fetchone()[0]
except Exception as e:
logger.error(f'获取会话总数失败: {e}')
return 0
def get_session_data(self, session_id: str) -> Optional[Dict]:
"""获取会话详细数据"""
conn = self.get_connection()
cursor = conn.cursor()
try:
# 获取会话基本信息
cursor.execute('''
SELECT s.*, p.name as patient_name
FROM detection_sessions s
LEFT JOIN patients p ON s.patient_id = p.id
WHERE s.id = ?
''', (session_id,))
session_row = cursor.fetchone()
if not session_row:
return None
session = dict(session_row)
# 解析设置JSON
if session['settings']:
try:
session['settings'] = json.loads(session['settings'])
except:
session['settings'] = {}
# 获取检测数据
cursor.execute('''
SELECT * FROM detection_data
WHERE session_id = ?
ORDER BY timestamp
''', (session_id,))
data_rows = cursor.fetchall()
session['data'] = []
for row in data_rows:
data_point = dict(row)
# 解析数据JSON
try:
data_point['data_value'] = json.loads(data_point['data_value'])
except:
pass
session['data'].append(data_point)
return session
except Exception as e:
logger.error(f'获取会话数据失败: {e}')
return None
# ==================== 检测数据管理 ====================
def save_detection_data(self, session_id: str, data: Dict[str, Any]):
"""保存检测数据"""
conn = self.get_connection()
cursor = conn.cursor()
try:
# 保存不同类型的数据
for data_type, data_value in data.items():
cursor.execute('''
INSERT INTO detection_data (session_id, data_type, data_value)
VALUES (?, ?, ?)
''', (session_id, data_type, json.dumps(data_value)))
conn.commit()
except Exception as e:
conn.rollback()
logger.error(f'保存检测数据失败: {e}')
raise
def get_latest_detection_data(self, session_id: str, limit: int = 10) -> List[Dict]:
"""获取最新的检测数据"""
conn = self.get_connection()
cursor = conn.cursor()
try:
cursor.execute('''
SELECT * FROM detection_data
WHERE session_id = ?
ORDER BY timestamp DESC
LIMIT ?
''', (session_id, limit))
rows = cursor.fetchall()
data_points = []
for row in rows:
data_point = dict(row)
try:
data_point['data_value'] = json.loads(data_point['data_value'])
except:
pass
data_points.append(data_point)
return data_points
except Exception as e:
logger.error(f'获取最新检测数据失败: {e}')
return []
# ==================== 分析结果管理 ====================
def save_analysis_result(self, session_id: str, analysis_result: Dict[str, Any]):
"""保存分析结果"""
conn = self.get_connection()
cursor = conn.cursor()
try:
for analysis_type, result_data in analysis_result.items():
cursor.execute('''
INSERT INTO analysis_results (session_id, analysis_type, result_data)
VALUES (?, ?, ?)
''', (session_id, analysis_type, json.dumps(result_data)))
conn.commit()
logger.info(f'保存分析结果: {session_id}')
except Exception as e:
conn.rollback()
logger.error(f'保存分析结果失败: {e}')
raise
def get_analysis_results(self, session_id: str) -> Dict[str, Any]:
"""获取分析结果"""
conn = self.get_connection()
cursor = conn.cursor()
try:
cursor.execute('''
SELECT * FROM analysis_results
WHERE session_id = ?
ORDER BY created_at DESC
''', (session_id,))
rows = cursor.fetchall()
results = {}
for row in rows:
analysis_type = row['analysis_type']
try:
result_data = json.loads(row['result_data'])
results[analysis_type] = result_data
except:
results[analysis_type] = row['result_data']
return results
except Exception as e:
logger.error(f'获取分析结果失败: {e}')
return {}
# ==================== 系统设置管理 ====================
def get_setting(self, key: str, default_value: Any = None) -> Any:
"""获取系统设置"""
conn = self.get_connection()
cursor = conn.cursor()
try:
cursor.execute('SELECT value FROM system_settings WHERE key = ?', (key,))
row = cursor.fetchone()
if row:
try:
return json.loads(row['value'])
except:
return row['value']
return default_value
except Exception as e:
logger.error(f'获取系统设置失败: {e}')
return default_value
def set_setting(self, key: str, value: Any, description: str = ''):
"""设置系统设置"""
conn = self.get_connection()
cursor = conn.cursor()
try:
value_str = json.dumps(value) if not isinstance(value, str) else value
cursor.execute('''
INSERT OR REPLACE INTO system_settings (key, value, description, updated_at)
VALUES (?, ?, ?, CURRENT_TIMESTAMP)
''', (key, value_str, description))
conn.commit()
logger.info(f'设置系统设置: {key}')
except Exception as e:
conn.rollback()
logger.error(f'设置系统设置失败: {e}')
raise
# ==================== 用户管理 ====================
def register_user(self, user_data: Dict[str, Any]) -> Dict[str, Any]:
"""用户注册"""
conn = self.get_connection()
cursor = conn.cursor()
try:
import hashlib
# 检查手机号是否已存在(如果提供了手机号)
if user_data.get('phone'):
cursor.execute('SELECT COUNT(*) FROM users WHERE phone = ?', (user_data['phone'],))
if cursor.fetchone()[0] > 0:
return {
'success': False,
'message': '手机号已存在'
}
user_id = str(uuid.uuid4())
# 密码MD5加密
password_hash = hashlib.md5(user_data['password'].encode()).hexdigest()
cursor.execute('''
INSERT INTO users (id, name, username, password, phone, is_active, user_type)
VALUES (?, ?, ?, ?, ?, ?, ?)
''', (
user_id,
user_data['name'],
user_data['username'],
password_hash,
user_data.get('phone'), # 手机号可选
0, # 新注册用户默认未激活,需要管理员审核
'user'
))
conn.commit()
logger.info(f'用户注册成功: {user_data["username"]}')
return {
'success': True,
'user_id': user_id,
'message': '注册成功'
}
except sqlite3.IntegrityError:
conn.rollback()
logger.error(f'用户名已存在: {user_data["username"]}')
return {
'success': False,
'message': '用户名已存在'
}
except Exception as e:
conn.rollback()
logger.error(f'用户注册失败: {e}')
return {
'success': False,
'message': '注册失败'
}
def authenticate_user(self, username: str, password: str) -> Optional[Dict]:
"""用户登录验证"""
conn = self.get_connection()
cursor = conn.cursor()
try:
import hashlib
password_hash = hashlib.md5(password.encode()).hexdigest()
cursor.execute('''
SELECT * FROM users
WHERE username = ? AND password = ? AND is_active = 1
''', (username, password_hash))
row = cursor.fetchone()
if row:
user = dict(row)
# 不返回密码
del user['password']
logger.info(f'用户登录成功: {username}')
return user
else:
logger.warning(f'用户登录失败: {username}')
return None
except Exception as e:
logger.error(f'用户验证失败: {e}')
return None
def get_user_by_phone(self, phone: str) -> Optional[Dict]:
"""根据手机号查询用户"""
conn = self.get_connection()
cursor = conn.cursor()
try:
cursor.execute('SELECT * FROM users WHERE phone = ?', (phone,))
row = cursor.fetchone()
if row:
user = dict(row)
# 不返回密码
del user['password']
return user
return None
except Exception as e:
logger.error(f'根据手机号查询用户失败: {e}')
return None
def get_users(self, page: int = 1, size: int = 10, status: str = 'all') -> List[Dict]:
"""获取用户列表"""
conn = self.get_connection()
cursor = conn.cursor()
try:
offset = (page - 1) * size
if status == 'pending':
cursor.execute('''
SELECT id, name, username, phone, register_date, is_active, user_type, created_at
FROM users
WHERE is_active = 0 AND user_type = 'user'
ORDER BY created_at DESC
LIMIT ? OFFSET ?
''', (size, offset))
elif status == 'active':
cursor.execute('''
SELECT id, name, username, phone, register_date, is_active, user_type, created_at
FROM users
WHERE is_active = 1
ORDER BY created_at DESC
LIMIT ? OFFSET ?
''', (size, offset))
else:
cursor.execute('''
SELECT id, name, username, phone, register_date, is_active, user_type, created_at
FROM users
ORDER BY created_at DESC
LIMIT ? OFFSET ?
''', (size, offset))
rows = cursor.fetchall()
return [dict(row) for row in rows]
except Exception as e:
logger.error(f'获取用户列表失败: {e}')
return []
def get_users_count(self, status: str = 'all') -> int:
"""获取用户总数"""
conn = self.get_connection()
cursor = conn.cursor()
try:
if status == 'pending':
cursor.execute('SELECT COUNT(*) FROM users WHERE is_active = 0 AND user_type = "user"')
elif status == 'active':
cursor.execute('SELECT COUNT(*) FROM users WHERE is_active = 1')
else:
cursor.execute('SELECT COUNT(*) FROM users')
return cursor.fetchone()[0]
except Exception as e:
logger.error(f'获取用户总数失败: {e}')
return 0
def approve_user(self, user_id: str, approved: bool = True):
"""审核用户"""
conn = self.get_connection()
cursor = conn.cursor()
try:
cursor.execute('''
UPDATE users SET
is_active = ?,
updated_at = CURRENT_TIMESTAMP
WHERE id = ?
''', (1 if approved else 0, user_id))
conn.commit()
status = '通过' if approved else '拒绝'
logger.info(f'用户审核{status}: {user_id}')
except Exception as e:
conn.rollback()
logger.error(f'用户审核失败: {e}')
raise
def get_user(self, user_id: str) -> Optional[Dict]:
"""获取单个用户信息"""
conn = self.get_connection()
cursor = conn.cursor()
try:
cursor.execute('''
SELECT id, name, username, phone, register_date, is_active, user_type, created_at, updated_at
FROM users WHERE id = ?
''', (user_id,))
row = cursor.fetchone()
return dict(row) if row else None
except Exception as e:
logger.error(f'获取用户信息失败: {e}')
return None
def update_user(self, user_id: str, user_data: Dict[str, Any]):
"""更新用户信息"""
conn = self.get_connection()
cursor = conn.cursor()
try:
# 如果包含密码,需要加密
if 'password' in user_data:
import hashlib
user_data['password'] = hashlib.md5(user_data['password'].encode()).hexdigest()
# 构建更新语句
fields = []
values = []
for key, value in user_data.items():
if key in ['name', 'username', 'password', 'is_active', 'user_type','phone']:
fields.append(f'{key} = ?')
values.append(value)
if fields:
fields.append('updated_at = CURRENT_TIMESTAMP')
values.append(user_id)
sql = f'UPDATE users SET {', '.join(fields)} WHERE id = ?'
cursor.execute(sql, values)
conn.commit()
logger.info(f'更新用户信息: {user_id}')
except Exception as e:
conn.rollback()
logger.error(f'更新用户信息失败: {e}')
raise
def delete_user(self, user_id: str):
"""删除用户"""
conn = self.get_connection()
cursor = conn.cursor()
try:
cursor.execute('DELETE FROM users WHERE id = ?', (user_id,))
conn.commit()
logger.info(f'删除用户: {user_id}')
except Exception as e:
conn.rollback()
logger.error(f'删除用户失败: {e}')
raise
def close(self):
"""关闭数据库连接"""
if self.connection:
self.connection.close()
self.connection = None
logger.info('数据库连接已关闭')