commit 344052185ee2017cfc52ab6820fa8403be9ca52a Author: zy <2894258754@qq.com> Date: Tue Jun 24 10:43:17 2025 +0800 123 diff --git a/123/business_logic.py b/123/business_logic.py new file mode 100644 index 0000000..a09cb30 --- /dev/null +++ b/123/business_logic.py @@ -0,0 +1,240 @@ +from datetime import date, datetime +from typing import Dict, Any, List, Optional, Tuple +from data_access import StudentDataAccess + + +class IDCardValidator: + """身份证验证工具类""" + + @staticmethod + def validate_id_card(id_card: str) -> Tuple[bool, str]: + """验证身份证号有效性""" + # 基本格式验证 + if len(id_card) != 18: + return False, "身份证号必须为18位" + + # 前17位必须是数字,最后一位可以是数字或X + if not (id_card[:-1].isdigit() and (id_card[-1].isdigit() or id_card[-1].upper() == 'X')): + return False, "身份证号格式不正确,前17位必须是数字,最后一位可以是数字或X" + + # 验证出生日期 + birth_date = id_card[6:14] + if not IDCardValidator.validate_birth_date(birth_date): + return False, "身份证号中的出生日期无效" + + # 验证校验码 + if not IDCardValidator.validate_check_code(id_card): + return False, "身份证号校验码不正确" + + return True, "身份证号有效" + + @staticmethod + def validate_birth_date(birth_date: str) -> bool: + """验证出生日期是否有效""" + try: + # 尝试解析日期 + year = int(birth_date[0:4]) + month = int(birth_date[4:6]) + day = int(birth_date[6:8]) + + # 检查日期范围 + if not (1900 <= year <= date.today().year): + return False + if not (1 <= month <= 12): + return False + + # 检查每月天数 + max_day = IDCardValidator.get_days_in_month(year, month) + if not (1 <= day <= max_day): + return False + + return True + except: + return False + + @staticmethod + def get_days_in_month(year: int, month: int) -> int: + """获取某年某月的天数""" + if month == 2: + return 29 if IDCardValidator.is_leap_year(year) else 28 + elif month in [4, 6, 9, 11]: + return 30 + else: + return 31 + + @staticmethod + def is_leap_year(year: int) -> bool: + """判断是否为闰年""" + return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0) + + @staticmethod + def validate_check_code(id_card: str) -> bool: + """验证身份证校验码""" + # 权重因子 + weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] + # 校验码对应表 + check_code_map = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'] + + # 计算加权和 + total = sum(int(id_card[i]) * weight[i] for i in range(17)) + # 计算校验码 + calculated_code = check_code_map[total % 11] + + # 比较校验码 + return id_card[-1].upper() == calculated_code + + @staticmethod + def get_gender(id_card: str) -> str: + """根据身份证号获取性别""" + if len(id_card) < 17: + return "未知" + gender_num = int(id_card[16]) + return "男" if gender_num % 2 == 1 else "女" + + @staticmethod + def get_birth_date(id_card: str) -> Optional[date]: + """从身份证号获取出生日期""" + if len(id_card) < 14: + return None + try: + birth_str = id_card[6:14] + return datetime.strptime(birth_str, "%Y%m%d").date() + except: + return None + + @staticmethod + def calculate_age(id_card: str) -> Optional[int]: + """根据身份证号计算年龄""" + birth_date = IDCardValidator.get_birth_date(id_card) + if not birth_date: + return None + + today = date.today() + age = today.year - birth_date.year + # 如果生日还没到,年龄减1 + if (today.month, today.day) < (birth_date.month, birth_date.day): + age -= 1 + return age + + +class StudentService: + def __init__(self, data_access: StudentDataAccess): + self.data_access = data_access + self.subject_name = { + 'math': '数学', + 'python': 'Python程序设计', + 'english': '英语', + 'physics': '物理', + 'sum': '总分' + } + + def validate_id_card(self, id_card: str) -> Tuple[bool, str]: + """验证身份证号格式""" + return IDCardValidator.validate_id_card(id_card) + + def is_id_card_exists(self, id_card: str, exclude_id: str = None) -> bool: + """检查身份证号是否已存在""" + students = self.data_access.get_all_students() + for sid, student in students.items(): + if exclude_id and sid == exclude_id: + continue + if student['basic_info'].get('id_card', '').upper() == id_card.upper(): + return True + return False + + def add_student(self, student_info: Dict[str, Any]) -> bool: + """添加新学生""" + student_id = student_info['basic_info']['id'] + + # 验证学号 + if not student_id.isdigit() or len(student_id) != 8: + raise ValueError("学号必须为8位数字!") + + # 验证身份证号 + id_card = student_info['basic_info'].get('id_card', '') + if not id_card: + raise ValueError("身份证号不能为空!") + + is_valid, msg = self.validate_id_card(id_card) + if not is_valid: + raise ValueError(f"身份证号无效: {msg}") + + if self.is_id_card_exists(id_card): + raise ValueError("该身份证号已存在!") + + # 自动填充性别和出生日期 + student_info['basic_info']['gender'] = IDCardValidator.get_gender(id_card) + birth_date = IDCardValidator.get_birth_date(id_card) + if birth_date: + student_info['basic_info']['birth_date'] = birth_date.strftime("%Y-%m-%d") + student_info['basic_info']['age'] = IDCardValidator.calculate_age(id_card) + + # 计算总分 + scores = student_info['score'] + scores['sum'] = sum([scores['math'], scores['python'], scores['english'], scores['physics']]) + + return self.data_access.add_student(student_id, student_info) + + def update_student(self, student_id: str, student_info: Dict[str, Any]) -> bool: + """更新学生信息""" + # 验证身份证号 + id_card = student_info['basic_info'].get('id_card', '') + if id_card: # 如果提供了身份证号才验证 + is_valid, msg = self.validate_id_card(id_card) + if not is_valid: + raise ValueError(f"身份证号无效: {msg}") + if self.is_id_card_exists(id_card, exclude_id=student_id): + raise ValueError("该身份证号已被其他学生使用!") + + # 自动更新性别和出生日期 + student_info['basic_info']['gender'] = IDCardValidator.get_gender(id_card) + birth_date = IDCardValidator.get_birth_date(id_card) + if birth_date: + student_info['basic_info']['birth_date'] = birth_date.strftime("%Y-%m-%d") + student_info['basic_info']['age'] = IDCardValidator.calculate_age(id_card) + + # 计算总分 + scores = student_info['score'] + scores['sum'] = sum([scores['math'], scores['python'], scores['english'], scores['physics']]) + + return self.data_access.update_student(student_id, student_info) + + def delete_student(self, student_id: str) -> bool: + """删除学生""" + return self.data_access.delete_student(student_id) + + def get_student(self, student_id: str) -> Dict[str, Any]: + """获取单个学生信息""" + return self.data_access.get_student(student_id) + + def get_all_students(self) -> Dict[str, Any]: + """获取所有学生信息""" + return self.data_access.get_all_students() + + def search_student_by_id(self, student_id: str) -> Dict[str, Any]: + """按学号查询学生信息""" + return self.data_access.get_student(student_id) + + def get_statistics(self) -> Dict[str, float]: + """获取统计信息""" + students = self.data_access.get_all_students().values() + if not students: + return {} + + total = len(students) + return { + 'total': total, + 'math_avg': sum(s['score']['math'] for s in students) / total, + 'python_avg': sum(s['score']['python'] for s in students) / total, + 'english_avg': sum(s['score']['english'] for s in students) / total, + 'physics_avg': sum(s['score']['physics'] for s in students) / total, + 'total_avg': sum(s['score']['sum'] for s in students) / total + } + + def get_sorted_students(self) -> List[Dict[str, Any]]: + """按总分排序获取学生""" + students = list(self.data_access.get_all_students().values()) + return sorted(students, key=lambda x: x['score']['sum'], reverse=True) + + def load_data(self): + pass \ No newline at end of file diff --git a/123/data_access.py b/123/data_access.py new file mode 100644 index 0000000..319c8a4 --- /dev/null +++ b/123/data_access.py @@ -0,0 +1,60 @@ +import json +import os +from typing import Dict, Any + + +class StudentDataAccess: + def __init__(self, file_path: str = 'student_data.json'): + self.file_path = file_path + + def load_data(self) -> Dict[str, Any]: + """从文件加载所有学生数据""" + try: + if os.path.exists(self.file_path): + with open(self.file_path, 'r', encoding='utf-8') as f: + return json.load(f) + return {} + except Exception as e: + raise Exception(f"加载数据时出错: {e}") + + def save_data(self, data: Dict[str, Any]) -> bool: + """保存所有学生数据到文件""" + try: + with open(self.file_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=4) + return True + except Exception as e: + raise Exception(f"保存数据时出错: {e}") + + def get_student(self, student_id: str) -> Dict[str, Any]: + """根据学号获取单个学生信息""" + data = self.load_data() + return data.get(student_id) + + def get_all_students(self) -> Dict[str, Any]: + """获取所有学生信息""" + return self.load_data() + + def add_student(self, student_id: str, student_info: Dict[str, Any]) -> bool: + """添加新学生""" + data = self.load_data() + if student_id in data: + raise Exception("该学号已存在!") + data[student_id] = student_info + return self.save_data(data) + + def update_student(self, student_id: str, student_info: Dict[str, Any]) -> bool: + """更新学生信息""" + data = self.load_data() + if student_id not in data: + raise Exception("该学号不存在!") + data[student_id] = student_info + return self.save_data(data) + + def delete_student(self, student_id: str) -> bool: + """删除学生""" + data = self.load_data() + if student_id not in data: + raise Exception("该学号不存在!") + del data[student_id] + return self.save_data(data) \ No newline at end of file diff --git a/123/presentation.py b/123/presentation.py new file mode 100644 index 0000000..ee2c6b0 --- /dev/null +++ b/123/presentation.py @@ -0,0 +1,295 @@ +import sys +from business_logic import StudentService, IDCardValidator +from data_access import StudentDataAccess + + +class StudentManagementSystem: + def __init__(self): + self.data_access = StudentDataAccess() + self.student_service = StudentService(self.data_access) + + def show_menu(self): + """显示主菜单""" + menu = """ +=== 学生信息管理系统 === +1. 显示所有学生信息 +2. 按学号查询学生信息 +3. 添加学生信息 +4. 修改学生信息 +5. 删除学生信息 +6. 统计学生信息 +7. 按总分排序显示 +8. 验证身份证号 +0. 退出系统 +""" + print(menu) + + def run(self): + """运行系统""" + self.student_service.load_data() + print("学生信息已成功加载!") + + while True: + self.show_menu() + choice = input("请选择操作(0-8): ").strip() + + if choice == '0': + print("感谢使用学生信息管理系统,再见!") + sys.exit() + elif choice == '1': + self.show_all_students() + elif choice == '2': + self.search_student() + elif choice == '3': + self.add_student() + elif choice == '4': + self.update_student() + elif choice == '5': + self.delete_student() + elif choice == '6': + self.show_statistics() + elif choice == '7': + self.show_sorted_students() + elif choice == '8': + self.validate_id_card() + else: + print("无效的选择,请重新输入!") + + input("\n按回车键继续...") + + def show_all_students(self): + """显示所有学生信息""" + students = self.student_service.get_all_students() + if not students: + print("当前没有学生信息!") + return + + print("\n=== 所有学生信息 ===") + print("学号\t姓名\t性别\t年龄\t班级\t总分") + for student_id, info in students.items(): + basic_info = info['basic_info'] + print(f"{student_id}\t{basic_info['name']}\t{basic_info.get('gender', '未知')}\t" + f"{basic_info.get('age', '未知')}\t{basic_info['class']}\t{info['score']['sum']}") + + def search_student(self): + """按学号查询学生信息""" + student_id = input("请输入要查询的学生学号: ") + student = self.student_service.search_student_by_id(student_id) + + if student: + print("\n=== 学生详细信息 ===") + print("基本信息:") + for key, value in student['basic_info'].items(): + print(f" {key}: {value}") + + print("\n成绩信息:") + for subject, score in student['score'].items(): + if subject in self.student_service.subject_name: + print(f" {self.student_service.subject_name[subject]}: {score}") + else: + print("未找到该学号的学生!") + + def add_student(self): + """添加新学生""" + print("\n=== 添加新学生 ===") + + # 输入学号 + while True: + student_id = input("请输入8位学号(如20230001): ").strip() + if not student_id.isdigit() or len(student_id) != 8: + print("学号必须为8位数字!") + continue + if self.student_service.search_student_by_id(student_id): + print("该学号已存在!") + continue + break + + # 输入身份证号 + while True: + id_card = input("请输入18位身份证号: ").strip().upper() + if not id_card: + print("身份证号不能为空!") + continue + + is_valid, msg = self.student_service.validate_id_card(id_card) + if not is_valid: + print(f"身份证号无效: {msg}") + continue + + if self.student_service.is_id_card_exists(id_card): + print("该身份证号已存在!") + continue + break + + # 自动获取性别和出生日期 + gender = IDCardValidator.get_gender(id_card) + birth_date = IDCardValidator.get_birth_date(id_card) + age = IDCardValidator.calculate_age(id_card) + + # 输入其他信息 + name = input("请输入姓名: ").strip() + class_name = input("请输入班级: ").strip() + admission_year = input("请输入入学年份: ").strip() + + # 输入成绩 + math_score = float(input("请输入数学成绩: ")) + python_score = float(input("请输入Python成绩: ")) + english_score = float(input("请输入英语成绩: ")) + physics_score = float(input("请输入物理成绩: ")) + total_score = math_score + python_score + english_score + physics_score + + # 创建学生信息字典 + student = { + 'basic_info': { + 'id': student_id, + 'id_card': id_card, + 'name': name, + 'gender': gender, + 'birth_date': birth_date.strftime("%Y-%m-%d") if birth_date else "", + 'age': age, + 'class': class_name, + 'admission_year': admission_year + }, + 'score': { + 'math': math_score, + 'python': python_score, + 'english': english_score, + 'physics': physics_score, + 'sum': total_score + } + } + + try: + if self.student_service.add_student(student): + print("学生信息添加成功!") + except Exception as e: + print(f"添加学生失败: {e}") + + def update_student(self): + """修改学生信息""" + student_id = input("请输入要修改的学生学号: ") + student = self.student_service.search_student_by_id(student_id) + + if not student: + print("未找到该学号的学生!") + return + + print("\n当前学生信息:") + print("基本信息:") + for key, value in student['basic_info'].items(): + print(f" {key}: {value}") + + print("\n成绩信息:") + for subject, score in student['score'].items(): + if subject in self.student_service.subject_name: + print(f" {self.student_service.subject_name[subject]}: {score}") + + print("\n请输入新的信息(直接回车保持原值):") + + # 更新基本信息 + basic_info = student['basic_info'] + for field in ['name', 'class', 'admission_year']: + new_value = input(f"{field}(当前:{basic_info[field]}): ").strip() + if new_value: + basic_info[field] = new_value + + # 更新身份证号 + while True: + new_id_card = input(f"身份证号(当前:{basic_info.get('id_card', '')}): ").strip().upper() + if not new_id_card: # 直接回车保持原值 + break + + is_valid, msg = self.student_service.validate_id_card(new_id_card) + if not is_valid: + print(f"身份证号无效: {msg}") + continue + + if self.student_service.is_id_card_exists(new_id_card, exclude_id=student_id): + print("该身份证号已被其他学生使用!") + continue + + basic_info['id_card'] = new_id_card + # 自动更新性别和出生日期 + basic_info['gender'] = IDCardValidator.get_gender(new_id_card) + birth_date = IDCardValidator.get_birth_date(new_id_card) + if birth_date: + basic_info['birth_date'] = birth_date.strftime("%Y-%m-%d") + basic_info['age'] = IDCardValidator.calculate_age(new_id_card) + break + + # 更新成绩 + scores = student['score'] + for subject in ['math', 'python', 'english', 'physics']: + new_score = input(f"{self.student_service.subject_name[subject]}(当前:{scores[subject]}): ").strip() + if new_score: + scores[subject] = float(new_score) + scores['sum'] = sum([scores['math'], scores['python'], scores['english'], scores['physics']]) + + try: + if self.student_service.update_student(student_id, student): + print("学生信息修改成功!") + except Exception as e: + print(f"修改学生信息失败: {e}") + + def delete_student(self): + """删除学生""" + student_id = input("请输入要删除的学生学号: ") + + confirm = input(f"确定要删除学号为 {student_id} 的学生吗?(y/n): ").lower() + if confirm == 'y': + try: + if self.student_service.delete_student(student_id): + print("学生信息删除成功!") + except Exception as e: + print(f"删除学生失败: {e}") + + def show_statistics(self): + """显示统计信息""" + stats = self.student_service.get_statistics() + if not stats: + print("当前没有学生信息!") + return + + print("\n=== 统计信息 ===") + print(f"学生总数: {stats['total']}") + print(f"数学平均分: {stats['math_avg']:.2f}") + print(f"Python平均分: {stats['python_avg']:.2f}") + print(f"英语平均分: {stats['english_avg']:.2f}") + print(f"物理平均分: {stats['physics_avg']:.2f}") + print(f"总分平均分: {stats['total_avg']:.2f}") + + def show_sorted_students(self): + """按总分排序显示""" + sorted_students = self.student_service.get_sorted_students() + if not sorted_students: + print("当前没有学生信息!") + return + + print("\n=== 按总分排序 ===") + print("排名\t学号\t姓名\t总分") + for rank, student in enumerate(sorted_students, 1): + print(f"{rank}\t{student['basic_info']['id']}\t{student['basic_info']['name']}\t{student['score']['sum']}") + + def validate_id_card(self): + """验证身份证号""" + id_card = input("请输入要验证的身份证号: ").strip().upper() + is_valid, msg = IDCardValidator.validate_id_card(id_card) + + if is_valid: + print("\n=== 身份证号有效 ===") + print(f"号码: {id_card}") + print(f"性别: {IDCardValidator.get_gender(id_card)}") + + birth_date = IDCardValidator.get_birth_date(id_card) + if birth_date: + print(f"出生日期: {birth_date.strftime('%Y-%m-%d')}") + print(f"年龄: {IDCardValidator.calculate_age(id_card)}岁") + + print("校验码验证通过") + else: + print(f"\n身份证号无效: {msg}") + + +if __name__ == "__main__": + system = StudentManagementSystem() + system.run() \ No newline at end of file