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.
168 lines
7.1 KiB
168 lines
7.1 KiB
import csv
|
|
import os.path
|
|
from datetime import date
|
|
from typing import List, Optional
|
|
|
|
from 面向对象.model.student import Student
|
|
|
|
|
|
class StudentDALCSV:
|
|
def __init__(self, file_path: str):
|
|
self.file_path = file_path
|
|
self._ensure_file_exists()
|
|
|
|
def _ensure_file_exists(self):
|
|
"""确保CSV文件存在并包含表头"""
|
|
if not os.path.exists(self.file_path):
|
|
with open(self.file_path, mode='w', encoding='utf-8', newline='') as file:
|
|
writer = csv.writer(file)
|
|
writer.writerow([
|
|
'stu_id', 'name', 'height', 'birth_date', 'enrollment_date', 'class_name', 'id_card'
|
|
])
|
|
|
|
def save_students(self, students: List[Student]) -> None:
|
|
"""将学生列表保存到CSV文件"""
|
|
with open(self.file_path, mode='w', encoding='utf-8', newline='') as file:
|
|
writer = csv.writer(file)
|
|
writer.writerow([
|
|
'stu_id', 'name', 'height', 'birth_date', 'enrollment_date', 'class_name', 'id_card'
|
|
])
|
|
for student in students:
|
|
writer.writerow([
|
|
student.stu_id,
|
|
student.name,
|
|
student.height,
|
|
student.birth_date.isoformat(),
|
|
student.enrollment_date.isoformat(),
|
|
student.class_name,
|
|
student.id_card or ''
|
|
])
|
|
|
|
def load_students(self) -> List[Student]:
|
|
"""从CSV文件加载学生数据"""
|
|
students = []
|
|
try:
|
|
with open(self.file_path, mode='r', encoding='utf-8') as file:
|
|
reader = csv.DictReader(file)
|
|
for row in reader:
|
|
try:
|
|
birth_date = date.fromisoformat(row['birth_date'])
|
|
enrollment_date = date.fromisoformat(row['enrollment_date'])
|
|
id_card = row['id_card'] if row['id_card'].strip() else None
|
|
|
|
students.append(Student(
|
|
stu_id=row['stu_id'],
|
|
name=row['name'],
|
|
height=int(row['height']),
|
|
birth_date=birth_date,
|
|
enrollment_date=enrollment_date,
|
|
class_name=row['class_name'],
|
|
id_card=id_card
|
|
))
|
|
except Exception as e:
|
|
print(f"解析CSV行时出错: {e}")
|
|
except FileNotFoundError:
|
|
# 文件不存在时返回空列表
|
|
pass
|
|
return students
|
|
|
|
def add_student(self, student: Student) -> bool:
|
|
"""添加学生,确保学号和身份证号都唯一"""
|
|
students = self.load_students()
|
|
for existing_student in students:
|
|
if existing_student.stu_id == student.stu_id:
|
|
return False # 学生 ID 已存在,添加失败
|
|
if existing_student.id_card == student.id_card and student.id_card is not None:
|
|
return False # 身份证号已存在,添加失败
|
|
students.append(student)
|
|
self.save_students(students)
|
|
return True
|
|
|
|
def find_student_by_id_card(self, id_card: str) -> Optional[Student]:
|
|
"""通过身份证号查找学生"""
|
|
students = self.load_students()
|
|
for student in students:
|
|
if student.id_card == id_card:
|
|
return student
|
|
return None
|
|
|
|
def find_student_by_stu_id(self, stu_id: str) -> Optional[Student]:
|
|
students = self.load_students()
|
|
for student in students:
|
|
if student.stu_id == stu_id:
|
|
return student
|
|
return None
|
|
|
|
def find_students_by_name(self, name: str) -> List[Student]:
|
|
students = self.load_students()
|
|
return [student for student in students if name.lower() in student.name.lower()]
|
|
|
|
def find_students_by_class_name(self, class_name: str) -> List[Student]:
|
|
students = self.load_students()
|
|
return [s for s in students if class_name.lower() in s.class_name.lower()]
|
|
|
|
def get_all_students(self) -> List[Student]:
|
|
return self.load_students()
|
|
|
|
def update_student(self, stu_id: str, updated_student: Student) -> bool:
|
|
"""更新学生全部信息,确保身份证号唯一(除了学生自己)"""
|
|
students = self.load_students()
|
|
for i, student in enumerate(students):
|
|
if student.stu_id == stu_id:
|
|
# 检查新身份证号是否被其他学生使用
|
|
for other_student in students:
|
|
if other_student.stu_id != stu_id and other_student.id_card == updated_student.id_card:
|
|
return False # 身份证号已被其他学生使用
|
|
students[i] = updated_student
|
|
self.save_students(students)
|
|
return True
|
|
return False
|
|
|
|
def update_student_partial(self, stu_id: str, name: Optional[str] = None, height: Optional[int] = None,
|
|
birth_date: Optional[date] = None, enrollment_date: Optional[date] = None,
|
|
class_name: Optional[str] = None, id_card: Optional[str] = None) -> bool:
|
|
"""部分更新学生信息,支持更新身份证号"""
|
|
students = self.load_students()
|
|
for i, student in enumerate(students):
|
|
if student.stu_id == stu_id:
|
|
if name is not None:
|
|
students[i].name = name
|
|
if height is not None:
|
|
students[i].height = height
|
|
if birth_date is not None:
|
|
students[i].birth_date = birth_date
|
|
if enrollment_date is not None:
|
|
students[i].enrollment_date = enrollment_date
|
|
if class_name is not None:
|
|
students[i].class_name = class_name
|
|
if id_card is not None:
|
|
# 检查新身份证号是否被其他学生使用
|
|
for other_student in students:
|
|
if other_student.stu_id != stu_id and other_student.id_card == id_card:
|
|
return False # 身份证号已被其他学生使用
|
|
students[i].id_card = id_card
|
|
self.save_students(students)
|
|
return True
|
|
return False
|
|
|
|
def delete_student(self, stu_id: str) -> bool:
|
|
students = self.load_students()
|
|
initial_length = len(students)
|
|
students = [student for student in students if student.stu_id != stu_id]
|
|
if len(students) < initial_length:
|
|
self.save_students(students)
|
|
return True
|
|
return False
|
|
|
|
def clear_all_students(self) -> None:
|
|
self.save_students([])
|
|
|
|
def get_student_count(self) -> int:
|
|
return len(self.load_students())
|
|
|
|
def check_student_exists(self, stu_id: str) -> bool:
|
|
return self.find_student_by_stu_id(stu_id) is not None
|
|
|
|
def check_id_card_exists(self, id_card: str) -> bool:
|
|
"""检查身份证号是否已存在"""
|
|
return self.find_student_by_id_card(id_card) is not None |