• 学生信息系统

    pv5itx83h released this 8 months ago | 1 commits to master since this release

    import csv
    import json
    import os
    import sqlite3
    from abc import ABC, abstractmethod
    from datetime import date
    from typing import List, Optional, Union

    学生类定义

    class Student:
    def init(self,
    name: str,
    id_card: str,
    stu_id: str,
    gender: Optional[bool] = None,
    height: Optional[int] = None,
    weight: Optional[float] = None,
    enrollment_date: Optional[Union[date, str]] = None,
    class_name: Optional[str] = None,
    major: str = None):
    self.name = name
    self.id_card = id_card
    self.stu_id = stu_id
    self.gender = gender
    self.height = height
    self.weight = weight
    if isinstance(enrollment_date, str):
    self.enrollment_date = date.fromisoformat(enrollment_date)
    else:
    self.enrollment_date = enrollment_date
    self.class_name = class_name
    self.major = major
    self.age, self.birthday = self._calculate_age_and_birthday()
    self._validation_errors = []
    self._validate_all()

    def _calculate_age_and_birthday(self):
        birth_year = int(self.id_card[6:10])
        birth_month = int(self.id_card[10:12])
        birth_day = int(self.id_card[12:14])
        birthday = date(birth_year, birth_month, birth_day)
        today = date.today()
        age = today.year - birth_year
        if (today.month, today.day) < (birth_month, birth_day):
            age -= 1
        return age, birthday
    
    def _validate_all(self):
        self._validate_id_card()
        self._validate_stu_id()
        self._validate_name()
        self._validate_enrollment_date()
        self._validate_height()
        self._validate_weight()
    
    def _validate_id_card(self):
        if len(self.id_card) != 18:
            self._validation_errors.append("身份证号必须为18位")
        # 简单的校验位验证,可根据国家标准完善
        try:
            int(self.id_card[:17])
        except ValueError:
            self._validation_errors.append("身份证号前17位必须为数字")
    
    def _validate_stu_id(self):
        if not self.stu_id:
            self._validation_errors.append("学号不能为空")
    
    def _validate_name(self):
        if not (2 <= len(self.name) <= 20):
            self._validation_errors.append("姓名长度需在2-20个字符之间")
        if any(char.isdigit() or not char.isalpha() for char in self.name):
            self._validation_errors.append("姓名不能包含数字和特殊符号")
    
    def _validate_enrollment_date(self):
        if self.enrollment_date and self.enrollment_date < self.birthday:
            self._validation_errors.append("入学日期不能早于出生日期")
    
    def _validate_height(self):
        if self.height is not None and not (50 <= self.height <= 250):
            self._validation_errors.append("身高需在50-250cm之间")
    
    def _validate_weight(self):
        if self.weight is not None and not (5 <= self.weight <= 300):
            self._validation_errors.append("体重需在5-300kg之间")
    
    @property
    def is_valid(self):
        return len(self._validation_errors) == 0
    
    def get_errors(self):
        return self._validation_errors.copy()
    
    def to_dict(self):
        return {
            'name': self.name,
            'id_card': self.id_card,
            'stu_id': self.stu_id,
            'gender': self.gender,
            'height': self.height,
            'weight': self.weight,
            'enrollment_date': self.enrollment_date.isoformat() if self.enrollment_date else None,
            'class_name': self.class_name,
            'major': self.major,
            'age': self.age,
            'birthday': self.birthday.isoformat()
        }
    
    @classmethod
    def from_dict(cls, data):
        return cls(
            name=data['name'],
            id_card=data['id_card'],
            stu_id=data['stu_id'],
            gender=data['gender'],
            height=data['height'],
            weight=data['weight'],
            enrollment_date=data['enrollment_date'],
            class_name=data['class_name'],
            major=data['major']
        )
    

    数据访问层接口

    class IStudentDAL(ABC):
    @abstractmethod
    def get_by_id(self, id_card: str) -> Optional[Student]:
    pass

    @abstractmethod
    def get_by_stu_id(self, stu_id: str) -> Optional[Student]:
        pass
    
    @abstractmethod
    def get_all(self) -> List[Student]:
        pass
    
    @abstractmethod
    def add(self, student: Student) -> bool:
        pass
    
    @abstractmethod
    def delete(self, id_card: str = None, stu_id: str = None) -> bool:
        pass
    
    @abstractmethod
    def update(self, student: Student) -> bool:
        pass
    

    CSV数据访问层实现

    class CSVStudentDAL(IStudentDAL):
    def init(self, file_path):
    self.file_path = file_path
    if not os.path.exists(file_path):
    with open(file_path, 'w', newline='') as f:
    writer = csv.DictWriter(f, fieldnames=Student.from_dict({}).to_dict().keys())
    writer.writeheader()

    def get_by_id(self, id_card: str) -> Optional[Student]:
        with open(self.file_path, 'r', newline='') as f:
            reader = csv.DictReader(f)
            for row in reader:
                if row['id_card'] == id_card:
                    return Student.from_dict(row)
        return None
    
    def get_by_stu_id(self, stu_id: str) -> Optional[Student]:
        with open(self.file_path, 'r', newline='') as f:
            reader = csv.DictReader(f)
            for row in reader:
                if row['stu_id'] == stu_id:
                    return Student.from_dict(row)
        return None
    
    def get_all(self) -> List[Student]:
        students = []
        with open(self.file_path, 'r', newline='') as f:
            reader = csv.DictReader(f)
            for row in reader:
                students.append(Student.from_dict(row))
        return students
    
    def add(self, student: Student) -> bool:
        if self.get_by_id(student.id_card) or self.get_by_stu_id(student.stu_id):
            return False
        with open(self.file_path, 'a', newline='') as f:
            writer = csv.DictWriter(f, fieldnames=student.to_dict().keys())
            writer.writerow(student.to_dict())
        return True
    
    def delete(self, id_card: str = None, stu_id: str = None) -> bool:
        students = self.get_all()
        initial_length = len(students)
        if id_card:
            students = [s for s in students if s.id_card != id_card]
        elif stu_id:
            students = [s for s in students if s.stu_id != stu_id]
        if len(students) < initial_length:
            with open(self.file_path, 'w', newline='') as f:
                writer = csv.DictWriter(f, fieldnames=students[0].to_dict().keys() if students else [])
                writer.writeheader()
                for s in students:
                    writer.writerow(s.to_dict())
            return True
        return False
    
    def update(self, student: Student) -> bool:
        students = self.get_all()
        for i, s in enumerate(students):
            if s.id_card == student.id_card or s.stu_id == student.stu_id:
                students[i] = student
                with open(self.file_path, 'w', newline='') as f:
                    writer = csv.DictWriter(f, fieldnames=students[0].to_dict().keys() if students else [])
                    writer.writeheader()
                    for s in students:
                        writer.writerow(s.to_dict())
                return True
        return False
    

    JSON数据访问层实现

    class JSONStudentDAL(IStudentDAL):
    def init(self, file_path):
    self.file_path = file_path
    if not os.path.exists(file_path):
    with open(file_path, 'w') as f:
    json.dump([], f)

    def get_by_id(self, id_card: str) -> Optional[Student]:
        with open(self.file_path, 'r') as f:
            data = json.load(f)
            for row in data:
                if row['id_card'] == id_card:
                    return Student.from_dict(row)
        return None
    
    def get_by_stu_id(self, stu_id: str) -> Optional[Student]:
        with open(self.file_path, 'r') as f:
            data = json.load(f)
            for row in data:
                if row['stu_id'] == stu_id:
                    return Student.from_dict(row)
        return None
    
    def get_all(self) -> List[Student]:
        with open(self.file_path, 'r') as f:
            data = json.load(f)
            return [Student.from_dict(row) for row in data]
    
    def add(self, student: Student) -> bool:
        if self.get_by_id(student.id_card) or self.get_by_stu_id(student.stu_id):
            return False
        with open(self.file_path, 'r') as f:
            data = json.load(f)
        data.append(student.to_dict())
        with open(self.file_path, 'w') as f:
            json.dump(data, f, indent=4)
        return True
    
    def delete(self, id_card: str = None, stu_id: str = None) -> bool:
        with open(self.file_path, 'r') as f:
            data = json.load(f)
        initial_length = len(data)
        if id_card:
            data = [s for s in data if s['id_card'] != id_card]
        elif stu_id:
            data = [s for s in data if s['stu_id'] != stu_id]
        if len(data) < initial_length:
            with open(self.file_path, 'w') as f:
                json.dump(data, f, indent=4)
            return True
        return False
    
    def update(self, student: Student) -> bool:
        with open(self.file_path, 'r') as f:
            data = json.load(f)
        for i, s in enumerate(data):
            if s['id_card'] == student.id_card or s['stu_id'] == student.stu_id:
                data[i] = student.to_dict()
                with open(self.file_path, 'w') as f:
                    json.dump(data, f, indent=4)
                return True
        return False
    

    SQLite数据访问层实现

    class SQLiteStudentDAL(IStudentDAL):
    def init(self, db_path):
    self.db_path = db_path
    self._create_table()

    def _create_table(self):
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS students (
                id_card TEXT PRIMARY KEY,
                stu_id TEXT UNIQUE,
                name TEXT,
                gender BOOLEAN,
                height INTEGER,
                weight REAL,
                enrollment_date TEXT,
                class_name TEXT,
                major TEXT,
                age INTEGER,
                birthday TEXT
            )
        ''')
        conn.commit()
        conn.close()
    
    def get_by_id(self, id_card: str) -> Optional[Student]:
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM students WHERE id_card =?", (id_card,))
        row = cursor.fetchone()
        conn.close()
        if row:
            data = dict(zip([description[0] for description in cursor.description], row))
            return Student.from_dict(data)
        return None
    
    def get_by_stu_id(self, stu_id: str) -> Optional[Student]:
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM students WHERE stu_id =?", (stu_id,))
        row = cursor.fetchone()
        conn.close()
        if row:
            data = dict(zip([description[0] for description in cursor.description], row))
            return Student.from_dict(data)
        return None
    
    def get_all(self) -> List[Student]:
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM students")
        rows = cursor.fetchall()
        conn.close()
        return [Student.from_dict(dict(zip([description[0] for description in cursor.description], row))) for row in
                rows]
    
    def add(self, student: Student) -> bool:
        if self.get_by_id(student.id_card) or self.get_by_stu_id(student.stu_id):
            return False
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        try:
            cursor.execute('''
                INSERT INTO students (id_card, stu_id, name, gender, height, weight, enrollment_date, class_name, major, age, birthday)
                VALUES (?,?,?,?,?,?,?,?,?,?,?)
            ''', (
                student.id_card, student.stu_id, student.name, student.gender, student.height, student.weight,
                student.enrollment_date.isoformat() if student.enrollment_date else None, student.class_name,
                student.major, student.age, student.birthday.isoformat()))
            conn.commit()
            return True
        except sqlite3.IntegrityError:
            return False
        finally:
            conn.close()
    
    def delete(self, id_card: str = None, stu_id: str = None) -> bool:
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        if id_card:
            cursor.execute("DELETE FROM students WHERE id_card =?", (id_card,))
        elif stu_id:
            cursor.execute("DELETE FROM students WHERE stu_id =?", (stu_id,))
        rows_affected = cursor.rowcount
        conn.commit()
        conn.close()
        return rows_affected > 0
    
    def update(self, student: Student) -> bool:
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        try:
            cursor.execute('''
                UPDATE students
                SET stu_id =?, name =?, gender =?, height =?, weight =?, enrollment_date =?, class_name =?, major =?, age =?, birthday =?
                WHERE id_card =?
            ''', (
                student.stu_id, student.name, student.gender, student.height, student.weight,
                student.enrollment_date.isoformat() if student.enrollment_date else None, student.class_name,
                student.major, student.age, student.birthday.isoformat(), student.id_card))
            rows_affected = cursor.rowcount
            conn.commit()
            return rows_affected > 0
        except sqlite3.IntegrityError:
            return False
        finally:
            conn.close()
    

    业务逻辑层

    class StudentBLL:
    def init(self, dal: IStudentDAL):
    self.dal = dal

    def add_student(self, student: Student) -> bool:
        if not student.is_valid:
            raise ValueError(f"学生数据无效: {', '.join(student.get_errors())}")
        return self.dal.add(student)
    
    def delete_student(self, id_card: str = None, stu_id: str = None) -> bool:
        return self.dal.delete(id_card, stu_id)
    
    def update_student(self, student: Student) -> bool:
        if not student.is_valid:
            raise ValueError(f"学生数据无效: {', '.join(student.get_errors())}")
        return self.dal.update(student)
    
    def get_student_by_id(self, id_card: str) -> Optional[Student]:
        return self.dal.get_by_id(id_card)
    
    def get_student_by_stu_id(self, stu_id: str) -> Optional[Student]:
        return self.dal.get_by_stu_id(stu_id)
    
    def get_all_students(self) -> List[Student]:
        return self.dal.get_all()
    
    def query_by_name(self, name: str) -> List[Student]:
        return [s for s in self.get_all_students() if name.lower() in s.name.lower()]
    
    def query_by_class(self, class_name: str) -> List[Student]:
        return [s for s in self.get_all_students() if class_name.lower() in s.class_name.lower()]
    
    def query_by_major(self, major: str) -> List[Student]:
        return [s for s in self.get_all_students() if major.lower() in s.major.lower()]
    
    def get_student_count(self) -> int:
        return len(self.get_all_students())
    
    def get_major_count(self) -> dict:
        major_count = {}
        for student in self.get_all_students():
            if student.major in major_count:
                major_count[student.major] += 1
            else:
                major_count[student.major] = 1
        return major_count
    
    def get_avg_height_by_class(self, class_name: str) -> float:
        students = [s for s in self.get_all_students() if s.class_name == class_name and s.height is not None]
        if not students:
            return 0
        return sum(s.height for s in students) / len(students)
    
    def get_avg_weight_by_class(self, class_name: str) -> float:
        students = [s for s in self.get_all_students() if s.class_name == class_name and s.weight is not None]
        if not students:
            return 0
        return sum(s.weight for s in students) / len(students)
    
    def get_avg_height_by_major(self, major: str) -> float:
        students = [s for s in self.get_all_students() if s.major == major and s.height is not None]
        if not students:
            return 0
        return sum(s.height for s in students) / len(students)
    
    def get_avg_weight_by_major(self, major: str) -> float:
        students = [s for s in self.get_all_students() if s.major == major and s.weight is not None]
        if not students:
            return 0
        return sum(s.weight for s in students) / len(students)
    
    def import_from_csv(self, file_path):
        with open(file_path, 'r', newline='') as f:
            reader = csv.DictReader(f)
            for row in reader:
                student = Student.from_dict(row)
                if student.is_valid:
                    self.add_student(student)
    
    def import_from_json(self, file_path):
        with open(file_path, 'r') as f:
            data = json.load(f)
            for row in data:
                student = Student.from_dict(row)
                if student.is_valid:
                    self.add_student(student)
    
    def export_to_csv(self, file_path):
        students = self.get_all_students()
        with open(file_path, 'w', newline='') as f:
            writer = csv.DictWriter(f, fieldnames=students[0].to_dict().keys() if students else [])
            writer.writeheader()
            for s in students:
                writer.writerow(s.to_dict())
    
    def export_to_json(self, file_path):
        students = self.get_all_students()
        with open(file_path, 'w') as f:
            json.dump([s.to_dict() for s in students], f, indent=4)
    

    用户界面层

    class StudentUI:
    def init(self, bll: StudentBLL):
    self.bll = bll

    def display_menu(self):
        print("\n===== 学生信息管理系统 =====")
        print("1. 添加学生信息")
        print("2. 删除学生信息")
        print("3. 修改学生信息")
        print("4. 查看学生详细信息")
        print("5. 查询学生信息")
        print("6. 统计信息")
        print("7. 数据导入")
        print("8. 数据导出")
        print("0. 退出系统")
        print("==========================")
    
    def display_query_menu(self):
        print("\n===== 查询学生信息 =====")
        print("1. 按学号查询")
        print("2. 按姓名查询")
        print("3. 按班级查询")
        print("4. 按专业查询")
        print("5. 返回上一级")
        print("======================")
    
    def display_stats_menu(self):
        print("\n===== 统计信息 =====")
        print("1. 学生总数")
        print("2. 各专业学生人数")
        print("3. 按班级计算平均身高")
        print("4. 按班级计算平均体重")
        print("5. 按专业计算平均身高")
        print("6. 按专业计算平均体重")
        print("7. 返回上一级")
        print("====================")
    
    def display_import_menu(self):
        print("\n===== 数据导入 =====")
        print("1. 从CSV导入")
        print("2. 从JSON导入")
        print("3. 返回上一级")
        print("====================")
    
    def display_export_menu(self):
        print("\n===== 数据导出 =====")
        print("1. 导出到CSV")
        print("2. 导出到JSON")
        print("3. 返回上一级")
        print("====================")
    
    def get_student_input(self, existing_student=None):
        """获取学生输入,支持使用现有学生数据作为默认值"""
        if existing_student:
            print(f"当前值: {existing_student.name}")
        name = input("请输入姓名 (直接回车保持不变): ") or (existing_student.name if existing_student else "")
    
        if existing_student:
            print(f"当前值: {existing_student.id_card}")
        id_card = input("请输入身份证号 (直接回车保持不变): ") or (existing_student.id_card if existing_student else "")
    
        if existing_student:
            print(f"当前值: {existing_student.stu_id}")
        stu_id = input("请输入学号 (直接回车保持不变): ") or (existing_student.stu_id if existing_student else "")
    
        if existing_student and existing_student.gender is not None:
            print(f"当前值: {existing_student.gender}")
        gender_str = input("请输入性别 (True/False,直接回车保持不变): ")
        gender = None
        if gender_str:
            gender = gender_str.lower() == 'true'
        elif existing_student:
            gender = existing_student.gender
    
        if existing_student and existing_student.height is not None:
            print(f"当前值: {existing_student.height}")
        height_str = input("请输入身高 (cm,直接回车保持不变): ")
        height = None
        if height_str:
            height = int(height_str)
        elif existing_student:
            height = existing_student.height
    
        if existing_student and existing_student.weight is not None:
            print(f"当前值: {existing_student.weight}")
        weight_str = input("请输入体重 (kg,直接回车保持不变): ")
        weight = None
        if weight_str:
            weight = float(weight_str)
        elif existing_student:
            weight = existing_student.weight
    
        if existing_student and existing_student.enrollment_date:
            print(f"当前值: {existing_student.enrollment_date.isoformat()}")
        enrollment_date = input("请输入入学日期 (YYYY-MM-DD,直接回车保持不变): ") or (
            existing_student.enrollment_date.isoformat() if existing_student and existing_student.enrollment_date else None
        )
    
        if existing_student:
            print(f"当前值: {existing_student.class_name}")
        class_name = input("请输入班级名称 (直接回车保持不变): ") or (
            existing_student.class_name if existing_student else "")
    
        if existing_student:
            print(f"当前值: {existing_student.major}")
        major = input("请输入专业 (直接回车保持不变): ") or (existing_student.major if existing_student else "")
    
        return Student(name, id_card, stu_id, gender, height, weight, enrollment_date, class_name, major)
    
    def run(self):
        while True:
            self.display_menu()
            choice = input("请选择操作: ")
    
            if choice == "1":
                self.add_student()
            elif choice == "2":
                self.delete_student()
            elif choice == "3":
                self.update_student()
            elif choice == "4":
                self.view_student_details()
            elif choice == "5":
                self.query_student()
            elif choice == "6":
                self.statistics()
            elif choice == "7":
                self.import_data()
            elif choice == "8":
                self.export_data()
            elif choice == "0":
                print("感谢使用,再见!")
                break
            else:
                print("无效选择,请重试!")
    
    def add_student(self):
        print("\n===== 添加学生信息 =====")
        try:
            student = self.get_student_input()
            if self.bll.add_student(student):
                print("添加成功!")
            else:
                print("添加失败,学号或身份证号可能已存在。")
        except ValueError as e:
            print(f"添加失败: {e}")
    
    def delete_student(self):
        print("\n===== 删除学生信息 =====")
        choice = input("按学号删除请输入1,按身份证号删除请输入2: ")
        if choice == "1":
            stu_id = input("请输入要删除的学号: ")
            if self.bll.delete_student(stu_id=stu_id):
                print("删除成功!")
            else:
                print("删除失败,学号不存在。")
        elif choice == "2":
            id_card = input("请输入要删除的身份证号: ")
            if self.bll.delete_student(id_card=id_card):
                print("删除成功!")
            else:
                print("删除失败,身份证号不存在。")
        else:
            print("无效选择,请重试!")
    
    def update_student(self):
        print("\n===== 修改学生信息 =====")
        stu_id = input("请输入要修改的学生学号: ")
        student = self.bll.get_student_by_stu_id(stu_id)
        if not student:
            print("学号不存在。")
            return
    
        print(f"当前信息: {student.to_dict()}")
        print("(直接回车表示不修改)")
    
        # 使用现有的学生数据作为默认值
        new_student = self.get_student_input(student)
    
        # 确保不修改ID和学号
        new_student.id_card = student.id_card
        new_student.stu_id = student.stu_id
    
        try:
            if self.bll.update_student(new_student):
                print("修改成功!")
            else:
                print("修改失败,可能是数据验证不通过。")
        except ValueError as e:
            print(f"修改失败: {e}")
    
    def view_student_details(self):
        print("\n===== 查看学生详细信息 =====")
        stu_id = input("请输入要查看的学生学号: ")
        student = self.bll.get_student_by_stu_id(stu_id)
        if student:
            print(student.to_dict())
        else:
            print("学号不存在。")
    
    def query_student(self):
        while True:
            self.display_query_menu()
            choice = input("请选择查询方式: ")
            if choice == "1":
                stu_id = input("请输入学号: ")
                student = self.bll.get_student_by_stu_id(stu_id)
                if student:
                    print(student.to_dict())
                else:
                    print("未找到该学生。")
            elif choice == "2":
                name = input("请输入姓名: ")
                students = self.bll.query_by_name(name)
                if students:
                    for s in students:
                        print(s.to_dict())
                else:
                    print("未找到匹配的学生。")
            elif choice == "3":
                class_name = input("请输入班级名称: ")
                students = self.bll.query_by_class(class_name)
                if students:
                    for s in students:
                        print(s.to_dict())
                else:
                    print("未找到匹配的学生。")
            elif choice == "4":
                major = input("请输入专业名称: ")
                students = self.bll.query_by_major(major)
                if students:
                    for s in students:
                        print(s.to_dict())
                else:
                    print("未找到匹配的学生。")
            elif choice == "5":
                break
            else:
                print("无效选择,请重试!")
    
    def statistics(self):
        while True:
            self.display_stats_menu()
            choice = input("请选择统计方式: ")
            if choice == "1":
                print(f"学生总数: {self.bll.get_student_count()}")
            elif choice == "2":
                major_count = self.bll.get_major_count()
                for major, count in major_count.items():
                    print(f"{major}: {count}人")
            elif choice == "3":
                class_name = input("请输入班级名称: ")
                avg_height = self.bll.get_avg_height_by_class(class_name)
                print(f"{class_name} 班级平均身高: {avg_height:.2f} cm")
            elif choice == "4":
                class_name = input("请输入班级名称: ")
                avg_weight = self.bll.get_avg_weight_by_class(class_name)
                print(f"{class_name} 班级平均体重: {avg_weight:.2f} kg")
            elif choice == "5":
                major = input("请输入专业名称: ")
                avg_height = self.bll.get_avg_height_by_major(major)
                print(f"{major} 专业平均身高: {avg_height:.2f} cm")
            elif choice == "6":
                major = input("请输入专业名称: ")
                avg_weight = self.bll.get_avg_weight_by_major(major)
                print(f"{major} 专业平均体重: {avg_weight:.2f} kg")
            elif choice == "7":
                break
            else:
                print("无效选择,请重试!")
    
    def import_data(self):
        while True:
            self.display_import_menu()
            choice = input("请选择导入方式: ")
            if choice == "1":
                file_path = input("请输入CSV文件路径: ")
                try:
                    self.bll.import_from_csv(file_path)
                    print("导入成功!")
                except Exception as e:
                    print(f"导入失败: {e}")
            elif choice == "2":
                file_path = input("请输入JSON文件路径: ")
                try:
                    self.bll.import_from_json(file_path)
                    print("导入成功!")
                except Exception as e:
                    print(f"导入失败: {e}")
            elif choice == "3":
                break
            else:
                print("无效选择,请重试!")
    
    def export_data(self):
        while True:
            self.display_export_menu()
            choice = input("请选择导出方式: ")
            if choice == "1":
                file_path = input("请输入导出的CSV文件路径: ")
                try:
                    self.bll.export_to_csv(file_path)
                    print("导出成功!")
                except Exception as e:
                    print(f"导出失败: {e}")
            elif choice == "2":
                file_path = input("请输入导出的JSON文件路径: ")
                try:
                    self.bll.export_to_json(file_path)
                    print("导出成功!")
                except Exception as e:
                    print(f"导出失败: {e}")
            elif choice == "3":
                break
            else:
                print("无效选择,请重试!")
    

    if name == "main":
    # 选择数据存储方式
    storage_choice = input("请选择数据存储方式 (1: CSV, 2: JSON, 3: SQLite): ")
    if storage_choice == "1":
    dal = CSVStudentDAL("students.csv")
    elif storage_choice == "2":
    dal = JSONStudentDAL("students.json")
    elif storage_choice == "3":
    dal = SQLiteStudentDAL("students.db")
    else:
    print("无效选择,默认使用SQLite。")
    dal = SQLiteStudentDAL("students.db")

    bll = StudentBLL(dal)
    ui = StudentUI(bll)
    print("欢迎使用学生信息管理系统!")
    ui.run()
    Downloads