You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
3.5 KiB
117 lines
3.5 KiB
import json
|
|
import os
|
|
from datetime import datetime
|
|
import pymysql
|
|
from sqlalchemy import create_engine, Column, String, Float, Integer, DateTime, Enum, ForeignKey
|
|
from sqlalchemy.ext.declarative import declarative_base
|
|
from sqlalchemy.orm import sessionmaker, relationship
|
|
from dotenv import load_dotenv
|
|
|
|
# 加载配置
|
|
load_dotenv()
|
|
Base = declarative_base()
|
|
|
|
|
|
# 修复数据库连接 - 处理端口号转换
|
|
def get_database_url():
|
|
host = os.getenv('MYSQL_HOST', 'localhost')
|
|
port = os.getenv('MYSQL_PORT', '3306')
|
|
# 确保端口是整数
|
|
try:
|
|
port = int(port)
|
|
except (ValueError, TypeError):
|
|
port = 3306 # 默认端口
|
|
|
|
user = os.getenv('MYSQL_USER', 'root')
|
|
password = os.getenv('MYSQL_PWD', '')
|
|
database = os.getenv('MYSQL_DB', 'roll_call_system')
|
|
|
|
return f"mysql+pymysql://{user}:{password}@{host}:{port}/{database}"
|
|
|
|
|
|
# 数据库连接
|
|
try:
|
|
engine = create_engine(
|
|
get_database_url(),
|
|
echo=False,
|
|
pool_recycle=3600,
|
|
connect_args={'charset': 'utf8mb4'}
|
|
)
|
|
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
|
except Exception as e:
|
|
print(f"数据库连接失败: {e}")
|
|
# 使用SQLite作为备用数据库
|
|
engine = create_engine('sqlite:///./roll_call.db', connect_args={"check_same_thread": False})
|
|
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
|
|
|
|
|
class Student(Base):
|
|
__tablename__ = "students"
|
|
student_id = Column(String(20), primary_key=True)
|
|
name = Column(String(50), nullable=False)
|
|
major = Column(String(50), nullable=False)
|
|
class_name = Column(String(50), nullable=False)
|
|
total_score = Column(Float, default=0)
|
|
call_count = Column(Integer, default=0)
|
|
|
|
def to_dict(self):
|
|
return {
|
|
'student_id': self.student_id,
|
|
'name': self.name,
|
|
'major': self.major,
|
|
'class_name': self.class_name,
|
|
'total_score': self.total_score,
|
|
'call_count': self.call_count
|
|
}
|
|
|
|
|
|
class RollCallRecord(Base):
|
|
__tablename__ = "roll_call_records"
|
|
record_id = Column(Integer, autoincrement=True, primary_key=True)
|
|
student_id = Column(String(20), ForeignKey("students.student_id"), nullable=False)
|
|
call_time = Column(DateTime, default=datetime.now)
|
|
call_mode = Column(Enum('random', 'order'), nullable=False)
|
|
status = Column(Enum('present', 'absent'), default='present')
|
|
answer_type = Column(String(20), nullable=True)
|
|
performance = Column(String(20), nullable=True)
|
|
score_delta = Column(Float, default=0)
|
|
|
|
# 添加关系
|
|
student = relationship("Student", backref="records")
|
|
|
|
def to_dict(self):
|
|
return {
|
|
'record_id': self.record_id,
|
|
'student_id': self.student_id,
|
|
'call_time': self.call_time.strftime("%Y-%m-%d %H:%M:%S"),
|
|
'call_mode': self.call_mode,
|
|
'status': self.status,
|
|
'answer_type': self.answer_type,
|
|
'performance': self.performance,
|
|
'score_delta': self.score_delta
|
|
}
|
|
|
|
|
|
class OrderCallStatus(Base):
|
|
__tablename__ = "order_call_status"
|
|
class_name = Column(String(50), primary_key=True)
|
|
current_index = Column(Integer, default=0)
|
|
|
|
|
|
# 初始化数据库
|
|
def init_db():
|
|
Base.metadata.create_all(bind=engine)
|
|
|
|
|
|
# 数据库会话依赖
|
|
def get_db():
|
|
db = SessionLocal()
|
|
try:
|
|
yield db
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
init_db()
|
|
print("数据库初始化完成!") |