from datetime import date from bll.StudentBLL import StudentBLL from dal.StudentDAL import StudentDAL from student.Student import Student class StudentTUI: 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("0. 退出系统") print("==========================") def run(self): while True: self.display_menu() choice = input("请选择操作: ").strip() if choice == "0": print("再见!") break elif choice == "1": self.add_student() elif choice == "2": self.delete_student() elif choice == "3": self.update_student() elif choice == "4": self.query_students() elif choice == "5": self.show_stats() elif choice == "6": self.import_export() elif choice == "7": self.clear_data() else: print("无效选择,请重试") def add_student(self): print("\n--- 添加学生 ---") name = input("姓名: ").strip() id_card = input("身份证号: ").strip() stu_id = input("学号: ").strip() gender = self.input_gender() height = self.input_int("身高(cm): ") weight = self.input_float("体重(kg): ") enrollment_date = self.input_date("入学日期(YYYY-MM-DD): ") class_name = input("班级: ").strip() major = input("专业: ").strip() try: student = Student( name=name, id_card=id_card, stu_id=stu_id, gender=gender, height=height, weight=weight, enrollment_date=enrollment_date, class_name=class_name, major=major ) self.bll.add_student(student) print("添加成功!") except ValueError as e: print(f"添加失败: {e}") def input_gender(self): """输入性别""" while True: gender = input("性别(1.男 2.女 3.跳过): ").strip() if gender == '1': return True elif gender == '2': return False elif gender == '3': return None else: print("无效选择,请重新输入") def input_int(self, prompt: str): """输入整数""" while True: value = input(prompt).strip() try: return int(value) if value else None except ValueError: print("请输入有效的整数") def input_float(self, prompt: str): """输入浮点数""" while True: value = input(prompt).strip() try: return float(value) if value else None except ValueError: print("请输入有效的数字") def input_date(self, prompt: str): """输入日期""" while True: try: date_str = input(prompt).strip() if not date_str: return None return date.fromisoformat(date_str) except ValueError: print("日期格式应为YYYY-MM-DD") def delete_student(self): print("\n--- 删除学生 ---") stu_id = input("请输入学号: ").strip() try: self.bll.delete_student(stu_id) print("删除成功!") except ValueError as e: print(f"删除失败: {e}") def update_student(self): print("\n--- 更新学生 ---") stu_id = input("请输入学号: ").strip() student = self.bll.get_student_by_stu_id(stu_id) if not student: print("学生不存在") return print(f"当前信息: {student}") name = input(f"新姓名({student.name}): ").strip() or student.name id_card = input(f"新身份证号({student.id_card}): ").strip() or student.id_card new_stu_id = input(f"新学号({student.stu_id}): ").strip() or student.stu_id gender = self.input_gender_update(student.gender) height = self.input_int(f"新身高({student.height}): ") or student.height weight = self.input_float(f"新体重({student.weight}): ") or student.weight enrollment_date = self.input_date_update(student.enrollment_date) class_name = input(f"新班级({student.class_name}): ").strip() or student.class_name major = input(f"新专业({student.major}): ").strip() or student.major try: updated_student = Student( name=name, id_card=id_card, stu_id=new_stu_id, gender=gender, height=height, weight=weight, enrollment_date=enrollment_date, class_name=class_name, major=major ) # 如果学号改变了,需要先删除旧记录 if new_stu_id != stu_id: self.bll.delete_student(stu_id) self.bll.add_student(updated_student) print("更新成功!") except ValueError as e: print(f"更新失败: {e}") def input_gender_update(self, current_gender): current = "男" if current_gender is True else "女" if current_gender is False else "未指定" print(f"当前性别: {current}") return self.input_gender() def input_date_update(self, current_date): """输入日期(更新时)""" if current_date: print(f"当前日期: {current_date.isoformat()}") return self.input_date("新的日期(YYYY-MM-DD): ") or current_date def query_students(self): print("\n--- 查询学生 ---") print("1. 按身份证号查询") print("2. 按学号查询") print("3. 按姓名查询") print("4. 按班级查询") print("5. 按专业查询") print("6. 所有学生") choice = input("请选择查询方式: ").strip() students = [] if choice == "1": id_card = input("请输入身份证号: ").strip() student = self.bll.get_student_by_id_card(id_card) if student: students = [student] elif choice == "2": stu_id = input("请输入学号: ").strip() student = self.bll.get_student_by_stu_id(stu_id) if student: students = [student] elif choice == "3": name = input("请输入姓名: ").strip() students = self.bll.search_students('name', name) elif choice == "4": class_name = input("请输入班级: ").strip() students = self.bll.search_students('class', class_name) elif choice == "5": major = input("请输入专业: ").strip() students = self.bll.search_students('major', major) elif choice == "6": students = self.bll.get_all_students() else: print("无效选择") return self.print_students(students) def print_students(self, students): if not students: print("没有找到学生") return print("\n身份证号\t学号\t姓名\t性别\t身高\t体重\t班级\t专业\t年龄") print("=" * 100) for s in students: gender = "男" if s.gender is True else "女" if s.gender is False else "未知" print(f"{s.id_card}\t{s.stu_id}\t{s.name}\t{gender}\t" f"{s.height or '--'}\t{s.weight or '--'}\t" f"{s.class_name or '--'}\t{s.major or '--'}\t" f"{s.age or '--'}") print(f"共找到 {len(students)} 名学生") def show_stats(self): print("\n--- 统计分析 ---") print("1. 学生总数") print("2. 专业分布") print("3. 平均身高") print("4. 平均体重") print("5. 按年龄范围查询") choice = input("请选择统计项目: ").strip() if choice == "1": count = self.bll.get_student_count() print(f"学生总数: {count}") elif choice == "2": major_counts = self.bll.get_major_counts() print("\n专业分布:") for major, count in major_counts.items(): print(f" {major}: {count}人") elif choice == "3": avg_height = self.bll.calculate_avg_height() print(f"平均身高: {avg_height:.1f} cm") elif choice == "4": avg_weight = self.bll.calculate_avg_weight() print(f"平均体重: {avg_weight:.1f} kg") elif choice == "5": min_age = int(input("最小年龄: ")) max_age = int(input("最大年龄: ")) students = self.bll.get_students_by_age(min_age, max_age) self.print_students(students) else: print("无效选择") def import_export(self): print("\n--- 导入导出 ---") print("1. 导出数据") print("2. 导入数据") choice = input("请选择操作: ").strip() if choice == "1": file_path = input("导出文件路径: ").strip() if self.bll.export_data(file_path): print("导出成功!") else: print("导出失败") elif choice == "2": file_path = input("导入文件路径: ").strip() if self.bll.import_data(file_path): print("导入成功!") else: print("导入失败") else: print("无效选择") def clear_data(self): confirm = input("确定要清空所有数据吗?(y/n): ").strip().lower() if confirm == 'y': if self.bll.clear_all(): print("数据已清空") else: print("清空失败")