Python+PyQt5实现简历自动生成工具

Written by

in

文章目录
  • 在当今竞争激烈的求职市场中,一份专业、规范的简历是获得面试机会的关键。然而,手动编写和排版简历往往耗时费力,特别是当我们需要针对不同职位定制多份简历时。本文介绍的基于PyQt5的自动化简历生成工具,将彻底改变这一现状。 该工具具有以下核心优势: 一站式管理:整合个人信息、教育背景、工作经历等所有模块 可视化编辑:直观的GUI界面,告别代码和命令行 多格式输出:支持PDF导出,确保跨平台兼容性 数据持久化:JSON格式保存/加载,简历数据永不丢失 模板化设计:多种风格模板满足不同行业需求
  • UI界面概览 左侧为标签式编辑面板,右侧为实时预览区,符合专业软件设计范式。
  • import sys import json import os from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QTextEdit, QPushButton, QComboBox, QListWidget, QListWidgetItem, QTabWidget, QFileDialog, QMessageBox, QFormLayout, QSpinBox, QDateEdit, QCheckBox, QGroupBox, QFrame) from PyQt5.QtCore import Qt, QDate from PyQt5.QtGui import QFont, QIcon, QColor, QPalette from fpdf import FPDF from datetime import datetime class ResumeGenerator(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle(“自动化简历生成工具”) self.setGeometry(100, 100, 1000, 750) # 尝试加载图标,如果失败则忽略 try: self.setWindowIcon(QIcon(“resume_icon.png”)) except: pass # 初始化UI self.init_ui() # 加载模板 self.load_templates() # 初始化简历数据结构 self.init_resume_data() # 当前编辑的项目索引 self.current_edu_index = -1 self.current_exp_index = -1 self.current_proj_index = -1 self.current_cert_index = -1 def init_ui(self): # 设置主窗口背景和全局样式 self.setStyleSheet(“”” QMainWindow { background-color: #f0f2f5; } QTabBar::tab { padding: 10px; border-top-left-radius: 5px; border-top-right-radius: 5px; margin-right: 2px; } QTabBar::tab:selected { background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:1 #e0e0e0); border-bottom: 2px solid #4CAF50; } QTabBar::tab:!selected { background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #e0e0e0, stop:1 #d0d0d0); } QLineEdit, QTextEdit, QComboBox, QSpinBox, QDateEdit { padding: 8px; border: 1px solid #ddd; border-radius: 4px; background: white; } QTextEdit { min-height: 100px; } QListWidget { border: 1px solid #ddd; background: white; border-radius: 4px; } QPushButton { padding: 8px 12px; border-radius: 4px; font-weight: bold; min-width: 80px; } QGroupBox { border: 1px solid #ddd; border-radius: 5px; margin-top: 10px; padding-top: 15px; background: white; } QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 3px; } “””) # 主窗口布局 main_widget = QWidget() self.setCentralWidget(main_widget) main_layout = QHBoxLayout() main_widget.setLayout(main_layout) main_layout.setContentsMargins(10, 10, 10, 10) main_layout.setSpacing(15) # 左侧面板 – 简历内容编辑 (70%宽度) self.left_panel = QTabWidget() self.left_panel.setTabPosition(QTabWidget.North) self.left_panel.setDocumentMode(True) main_layout.addWidget(self.left_panel, 7) # 右侧面板 – 预览和操作 (30%宽度) right_panel = QWidget() right_panel.setMaximumWidth(350) right_layout = QVBoxLayout() right_layout.setContentsMargins(5, 5, 5, 5) right_panel.setLayout(right_layout) main_layout.addWidget(right_panel, 3) # 添加标签页 self.add_personal_info_tab() self.add_summary_tab() self.add_education_tab() self.add_experience_tab() self.add_skills_tab() self.add_projects_tab() self.add_certifications_tab() self.add_languages_tab() # 右侧面板内容 # 模板选择组 template_group = QGroupBox(“简历模板”) template_layout = QVBoxLayout() template_group.setLayout(template_layout) self.template_combo = QComboBox() self.template_combo.setStyleSheet(“”” QComboBox { padding: 8px; border: 1px solid #4CAF50; border-radius: 4px; background: white; } QComboBox::drop-down { border: none; } “””) template_layout.addWidget(self.template_combo) # 操作按钮组 button_group = QGroupBox(“操作”) button_layout = QVBoxLayout() button_group.setLayout(button_layout) # 预览按钮 self.preview_btn = QPushButton(“📄 预览简历”) self.preview_btn.setStyleSheet(“”” QPushButton { background-color: #4CAF50; color: white; } QPushButton:hover { background-color: #45a049; } “””) self.preview_btn.clicked.connect(self.preview_resume) button_layout.addWidget(self.preview_btn) # 导出按钮 self.export_btn = QPushButton(“💾 导出PDF”) self.export_btn.setStyleSheet(“”” QPushButton { background-color: #2196F3; color: white; } QPushButton:hover { background-color: #0b7dda; } “””) self.export_btn.clicked.connect(self.export_to_pdf) button_layout.addWidget(self.export_btn) # 分隔线 line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) button_layout.addWidget(line) # 保存按钮 self.save_btn = QPushButton(“💾 保存数据”) self.save_btn.setStyleSheet(“”” QPushButton { background-color: #FF9800; color: white; } QPushButton:hover { background-color: #e68a00; } “””) self.save_btn.clicked.connect(self.save_resume_data) button_layout.addWidget(self.save_btn) # 加载按钮 self.load_btn = QPushButton(“📂 加载数据”) self.load_btn.setStyleSheet(“”” QPushButton { background-color: #9C27B0; color: white; } QPushButton:hover { background-color: #7b1fa2; } “””) self.load_btn.clicked.connect(self.load_resume_data) button_layout.addWidget(self.load_btn) # 预览区域组 preview_group = QGroupBox(“简历预览”) preview_layout = QVBoxLayout() preview_group.setLayout(preview_layout) self.preview_text = QTextEdit() self.preview_text.setReadOnly(True) self.preview_text.setStyleSheet(“”” QTextEdit { background-color: #f9f9f9; border: 1px solid #ddd; border-radius: 4px; } “””) preview_layout.addWidget(self.preview_text) # 添加到右侧面板 right_layout.addWidget(template_group) right_layout.addWidget(button_group) right_layout.addWidget(preview_group) # 设置标签页颜色 self.set_tab_colors() def set_tab_colors(self): #为每个标签页设置不同的颜色 tab_colors = [ (“#FF5252”, “#FFFFFF”), # 红色 (“#FF9800”, “#FFFFFF”), # 橙色 (“#FFEB3B”, “#000000”), # 黄色 (“#4CAF50”, “#FFFFFF”), # 绿色 (“#2196F3”, “#FFFFFF”), # 蓝色 (“#673AB7”, “#FFFFFF”), # 深紫色 (“#E91E63”, “#FFFFFF”), # 粉色 (“#607D8B”, “#FFFFFF”) # 蓝灰色 ] # 方法1:统一设置QTabBar样式(推荐) tab_bar = self.left_panel.tabBar() tab_bar.setStyleSheet(“”” QTabBar::tab { padding: 10px; border-top-left-radius: 5px; border-top-right-radius: 5px; margin-right: 2px; } QTabBar::tab:selected { background: white; border-bottom: 2px solid #4CAF50; } QTabBar::tab:!selected { background: #e0e0e0; } “””) def init_resume_data(self): “””初始化简历数据结构””” self.resume_data = { “personal_info”: { “name”: “”, “email”: “”, “phone”: “”, “address”: “”, “linkedin”: “”, “github”: “”, “website”: “” }, “summary”: “”, “education”: [], “experience”: [], “skills”: [], “projects”: [], “certifications”: [], “languages”: [] } def add_personal_info_tab(self): tab = QWidget() layout = QVBoxLayout() tab.setLayout(layout) # 使用GroupBox组织内容 group = QGroupBox(“个人信息”) form_layout = QFormLayout() group.setLayout(form_layout) # 创建带图标的输入字段 self.name_edit = self.create_line_edit(“👤”, “姓名”) self.email_edit = self.create_line_edit(“✉️”, “邮箱”) self.phone_edit = self.create_line_edit(“📱”, “电话”) self.address_edit = self.create_line_edit(“🏠”, “地址”) self.linkedin_edit = self.create_line_edit(“🔗”, “LinkedIn”) self.github_edit = self.create_line_edit(“💻”, “GitHub”) self.website_edit = self.create_line_edit(“🌐”, “个人网站”) # 添加到表单 form_layout.addRow(“姓名:”, self.name_edit) form_layout.addRow(“邮箱:”, self.email_edit) form_layout.addRow(“电话:”, self.phone_edit) form_layout.addRow(“地址:”, self.address_edit) form_layout.addRow(“LinkedIn:”, self.linkedin_edit) form_layout.addRow(“GitHub:”, self.github_edit) form_layout.addRow(“个人网站:”, self.website_edit) layout.addWidget(group) layout.addStretch() self.left_panel.addTab(tab, “个人信息”) def create_line_edit(self, icon, placeholder): “””创建带样式的QLineEdit””” line_edit = QLineEdit() line_edit.setPlaceholderText(f”{icon} {placeholder}”) line_edit.setStyleSheet(“”” QLineEdit { padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-size: 14px; } QLineEdit:focus { border: 1px solid #4CAF50; } “””) return line_edit def add_summary_tab(self): tab = QWidget() layout = QVBoxLayout() tab.setLayout(layout) group = QGroupBox(“职业概述”) group_layout = QVBoxLayout() group.setLayout(group_layout) self.summary_edit = QTextEdit() self.summary_edit.setPlaceholderText(“在这里输入你的职业概述…”) self.summary_edit.setStyleSheet(“”” QTextEdit { padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-size: 14px; } QTextEdit:focus { border: 1px solid #2196F3; } “””) group_layout.addWidget(self.summary_edit) layout.addWidget(group) layout.addStretch() self.left_panel.addTab(tab, “职业概述”) def add_education_tab(self): tab = QWidget() layout = QVBoxLayout() tab.setLayout(layout) # 教育经历表单组 form_group = QGroupBox(“添加/编辑教育经历”) form_layout = QFormLayout() form_group.setLayout(form_layout) # 创建输入字段 self.edu_school_edit = self.create_line_edit(“🏫”, “学校名称”) self.edu_degree_edit = self.create_line_edit(“🎓”, “学位”) self.edu_field_edit = self.create_line_edit(“📚”, “专业”) self.edu_start_date = QDateEdit() self.edu_end_date = QDateEdit() self.edu_current = QCheckBox(“至今”) self.edu_gpa_edit = self.create_line_edit(“📊”, “GPA”) self.edu_description = QTextEdit() # 设置日期控件 self.edu_start_date.setCalendarPopup(True) self.edu_end_date.setCalendarPopup(True) self.edu_current.stateChanged.connect(self.toggle_edu_end_date) # 添加到表单 form_layout.addRow(“学校:”, self.edu_school_edit) form_layout.addRow(“学位:”, self.edu_degree_edit) form_layout.addRow(“专业:”, self.edu_field_edit) form_layout.addRow(“开始日期:”, self.edu_start_date) form_layout.addRow(“结束日期:”, self.edu_end_date) form_layout.addRow(self.edu_current) form_layout.addRow(“GPA:”, self.edu_gpa_edit) form_layout.addRow(“描述:”, self.edu_description) # 按钮布局 btn_layout = QHBoxLayout() self.add_edu_btn = self.create_button(“➕ 添加”, “#4CAF50”) self.add_edu_btn.clicked.connect(self.add_education) self.update_edu_btn = self.create_button(“🔄 更新”, “#2196F3”) self.update_edu_btn.clicked.connect(self.update_education) self.remove_edu_btn = self.create_button(“❌ 删除”, “#F44336”) self.remove_edu_btn.clicked.connect(self.remove_education) btn_layout.addWidget(self.add_edu_btn) btn_layout.addWidget(self.update_edu_btn) btn_layout.addWidget(self.remove_edu_btn) # 教育经历列表组 list_group = QGroupBox(“教育经历列表”) list_layout = QVBoxLayout() list_group.setLayout(list_layout) self.edu_list = QListWidget() self.edu_list.itemClicked.connect(self.load_education) self.edu_list.setStyleSheet(“”” QListWidget { font-size: 14px; } QListWidget::item { padding: 8px; border-bottom: 1px solid #eee; } QListWidget::item:hover { background-color: #f0f0f0; } QListWidget::item:selected { background-color: #e3f2fd; color: #000; } “””) list_layout.addWidget(self.edu_list) # 添加到主布局 layout.addWidget(form_group) layout.addLayout(btn_layout) layout.addWidget(list_group) self.left_panel.addTab(tab, “教育经历”) def create_button(self, text, color): “””创建带样式的按钮””” btn = QPushButton(text) btn.setStyleSheet(f””” QPushButton {{ background-color: {color}; color: white; padding: 8px 12px; border-radius: 4px; font-weight: bold; }} QPushButton:hover {{ background-color: {self.darken_color(color)}; }} “””) return btn def darken_color(self, hex_color, factor=0.8): “””使颜色变暗””” color = QColor(hex_color) return color.darker(int(1/factor*100)).name() def add_experience_tab(self): tab = QWidget() layout = QVBoxLayout() tab.setLayout(layout) form_group = QGroupBox(“添加/编辑工作经历”) form_layout = QFormLayout() form_group.setLayout(form_layout) self.exp_company_edit = self.create_line_edit(“🏢”, “公司名称”) self.exp_position_edit = self.create_line_edit(“💼”, “职位”) self.exp_start_date = QDateEdit() self.exp_end_date = QDateEdit() self.exp_current = QCheckBox(“至今”) self.exp_description = QTextEdit() self.exp_start_date.setCalendarPopup(True) self.exp_end_date.setCalendarPopup(True) self.exp_current.stateChanged.connect(self.toggle_exp_end_date) form_layout.addRow(“公司:”, self.exp_company_edit) form_layout.addRow(“职位:”, self.exp_position_edit) form_layout.addRow(“开始日期:”, self.exp_start_date) form_layout.addRow(“结束日期:”, self.exp_end_date) form_layout.addRow(self.exp_current) form_layout.addRow(“描述:”, self.exp_description) btn_layout = QHBoxLayout() self.add_exp_btn = self.create_button(“➕ 添加”, “#4CAF50”) self.add_exp_btn.clicked.connect(self.add_experience) self.update_exp_btn = self.create_button(“🔄 更新”, “#2196F3”) self.update_exp_btn.clicked.connect(self.update_experience) self.remove_exp_btn = self.create_button(“❌ 删除”, “#F44336”) self.remove_exp_btn.clicked.connect(self.remove_experience) btn_layout.addWidget(self.add_exp_btn) btn_layout.addWidget(self.update_exp_btn) btn_layout.addWidget(self.remove_exp_btn) list_group = QGroupBox(“工作经历列表”) list_layout = QVBoxLayout() list_group.setLayout(list_layout) self.exp_list = QListWidget() self.exp_list.itemClicked.connect(self.load_experience) list_layout.addWidget(self.exp_list) layout.addWidget(form_group) layout.addLayout(btn_layout) layout.addWidget(list_group) self.left_panel.addTab(tab, “工作经历”) def add_skills_tab(self): tab = QWidget() layout = QVBoxLayout() tab.setLayout(layout) form_group = QGroupBox(“添加技能”) form_layout = QVBoxLayout() form_group.setLayout(form_layout) skill_layout = QHBoxLayout() self.skill_edit = self.create_line_edit(“🔧”, “技能名称”) self.skill_level_combo = QComboBox() self.skill_level_combo.addItems([“初级”, “中级”, “高级”, “专家”]) skill_layout.addWidget(self.skill_edit) skill_layout.addWidget(self.skill_level_combo) btn_layout = QHBoxLayout() self.add_skill_btn = self.create_button(“➕ 添加技能”, “#4CAF50”) self.add_skill_btn.clicked.connect(self.add_skill) self.remove_skill_btn = self.create_button(“❌ 删除选中”, “#F44336”) self.remove_skill_btn.clicked.connect(self.remove_skill) btn_layout.addWidget(self.add_skill_btn) btn_layout.addWidget(self.remove_skill_btn) list_group = QGroupBox(“技能列表”) list_layout = QVBoxLayout() list_group.setLayout(list_layout) self.skill_list = QListWidget() list_layout.addWidget(self.skill_list) form_layout.addWidget(QLabel(“添加技能:”)) form_layout.addLayout(skill_layout) form_layout.addLayout(btn_layout) layout.addWidget(form_group) layout.addWidget(list_group) self.left_panel.addTab(tab, “技能”) def add_projects_tab(self): tab = QWidget() layout = QVBoxLayout() tab.setLayout(layout) form_group = QGroupBox(“添加/编辑项目”) form_layout = QFormLayout() form_group.setLayout(form_layout) self.proj_name_edit = self.create_line_edit(“📂”, “项目名称”) self.proj_role_edit = self.create_line_edit(“👤”, “你的角色”) self.proj_start_date = QDateEdit() self.proj_end_date = QDateEdit() self.proj_current = QCheckBox(“进行中”) self.proj_description = QTextEdit() self.proj_url_edit = self.create_line_edit(“🔗”, “项目URL”) self.proj_start_date.setCalendarPopup(True) self.proj_end_date.setCalendarPopup(True) self.proj_current.stateChanged.connect(self.toggle_proj_end_date) form_layout.addRow(“项目名称:”, self.proj_name_edit) form_layout.addRow(“你的角色:”, self.proj_role_edit) form_layout.addRow(“开始日期:”, self.proj_start_date) form_layout.addRow(“结束日期:”, self.proj_end_date) form_layout.addRow(self.proj_current) form_layout.addRow(“项目URL:”, self.proj_url_edit) form_layout.addRow(“描述:”, self.proj_description) btn_layout = QHBoxLayout() self.add_proj_btn = self.create_button(“➕ 添加”, “#4CAF50”) self.add_proj_btn.clicked.connect(self.add_project) self.update_proj_btn = self.create_button(“🔄 更新”, “#2196F3”) self.update_proj_btn.clicked.connect(self.update_project) self.remove_proj_btn = self.create_button(“❌ 删除”, “#F44336”) self.remove_proj_btn.clicked.connect(self.remove_project) btn_layout.addWidget(self.add_proj_btn) btn_layout.addWidget(self.update_proj_btn) btn_layout.addWidget(self.remove_proj_btn) list_group = QGroupBox(“项目列表”) list_layout = QVBoxLayout() list_group.setLayout(list_layout) self.proj_list = QListWidget() self.proj_list.itemClicked.connect(self.load_project) list_layout.addWidget(self.proj_list) layout.addWidget(form_group) layout.addLayout(btn_layout) layout.addWidget(list_group) self.left_panel.addTab(tab, “项目经历”) def add_certifications_tab(self): tab = QWidget() layout = QVBoxLayout() tab.setLayout(layout) form_group = QGroupBox(“添加/编辑证书”) form_layout = QFormLayout() form_group.setLayout(form_layout) self.cert_name_edit = self.create_line_edit(“📜”, “证书名称”) self.cert_org_edit = self.create_line_edit(“🏛️”, “颁发机构”) self.cert_date = QDateEdit() self.cert_url_edit = self.create_line_edit(“🔗”, “证书URL”) self.cert_date.setCalendarPopup(True) form_layout.addRow(“证书名称:”, self.cert_name_edit) form_layout.addRow(“颁发机构:”, self.cert_org_edit) form_layout.addRow(“获得日期:”, self.cert_date) form_layout.addRow(“证书URL:”, self.cert_url_edit) btn_layout = QHBoxLayout() self.add_cert_btn = self.create_button(“➕ 添加”, “#4CAF50”) self.add_cert_btn.clicked.connect(self.add_certification) self.update_cert_btn = self.create_button(“🔄 更新”, “#2196F3”) self.update_cert_btn.clicked.connect(self.update_certification) self.remove_cert_btn = self.create_button(“❌ 删除”, “#F44336”) self.remove_cert_btn.clicked.connect(self.remove_certification) btn_layout.addWidget(self.add_cert_btn) btn_layout.addWidget(self.update_cert_btn) btn_layout.addWidget(self.remove_cert_btn) list_group = QGroupBox(“证书列表”) list_layout = QVBoxLayout() list_group.setLayout(list_layout) self.cert_list = QListWidget() self.cert_list.itemClicked.connect(self.load_certification) list_layout.addWidget(self.cert_list) layout.addWidget(form_group) layout.addLayout(btn_layout) layout.addWidget(list_group) self.left_panel.addTab(tab, “证书”) def add_languages_tab(self): tab = QWidget() layout = QVBoxLayout() tab.setLayout(layout) form_group = QGroupBox(“添加语言”) form_layout = QVBoxLayout() form_group.setLayout(form_layout) lang_layout = QHBoxLayout() self.lang_edit = self.create_line_edit(“🌐”, “语言”) self.lang_level_combo = QComboBox() self.lang_level_combo.addItems([“初级”, “中级”, “高级”, “母语”]) lang_layout.addWidget(self.lang_edit) lang_layout.addWidget(self.lang_level_combo) btn_layout = QHBoxLayout() self.add_lang_btn = self.create_button(“➕ 添加语言”, “#4CAF50”) self.add_lang_btn.clicked.connect(self.add_language) self.remove_lang_btn = self.create_button(“❌ 删除选中”, “#F44336”) self.remove_lang_btn.clicked.connect(self.remove_language) btn_layout.addWidget(self.add_lang_btn) btn_layout.addWidget(self.remove_lang_btn) list_group = QGroupBox(“语言列表”) list_layout = QVBoxLayout() list_group.setLayout(list_layout) self.lang_list = QListWidget() list_layout.addWidget(self.lang_list) form_layout.addWidget(QLabel(“添加语言:”)) form_layout.addLayout(lang_layout) form_layout.addLayout(btn_layout) layout.addWidget(form_group) layout.addWidget(list_group) self.left_panel.addTab(tab, “语言能力”) def toggle_edu_end_date(self, state): self.edu_end_date.setEnabled(not bool(state)) def toggle_exp_end_date(self, state): self.exp_end_date.setEnabled(not bool(state)) def toggle_proj_end_date(self, state): self.proj_end_date.setEnabled(not bool(state)) def load_templates(self): “””加载简历模板””” templates = [ “🌈 多彩创意模板”, “💼 专业商务模板”, “👔 传统经典模板”, “🎨 现代简约模板”, “📊 数据分析师模板”, “💻 开发者模板”, “🎓 学术模板”, “✏️ 设计师模板” ] self.template_combo.addItems(templates) def collect_personal_info(self): self.resume_data[“personal_info”] = { “name”: self.name_edit.text(), “email”: self.email_edit.text(), “phone”: self.phone_edit.text(), “address”: self.address_edit.text(), “linkedin”: self.linkedin_edit.text(), “github”: self.github_edit.text(), “website”: self.website_edit.text() } def collect_summary(self): self.resume_data[“summary”] = self.summary_edit.toPlainText() def add_education(self): self.collect_personal_info() edu = { “school”: self.edu_school_edit.text(), “degree”: self.edu_degree_edit.text(), “field”: self.edu_field_edit.text(), “start_date”: self.edu_start_date.date().toString(“yyyy-MM-dd”), “end_date”: “” if self.edu_current.isChecked() else self.edu_end_date.date().toString(“yyyy-MM-dd”), “current”: self.edu_current.isChecked(), “gpa”: self.edu_gpa_edit.text(), “description”: self.edu_description.toPlainText() } self.resume_data[“education”].append(edu) self.update_education_list() self.clear_education_form() def update_education(self): if self.current_edu_index == -1: return edu = { “school”: self.edu_school_edit.text(), “degree”: self.edu_degree_edit.text(), “field”: self.edu_field_edit.text(), “start_date”: self.edu_start_date.date().toString(“yyyy-MM-dd”), “end_date”: “” if self.edu_current.isChecked() else self.edu_end_date.date().toString(“yyyy-MM-dd”), “current”: self.edu_current.isChecked(), “gpa”: self.edu_gpa_edit.text(), “description”: self.edu_description.toPlainText() } self.resume_data[“education”][self.current_edu_index] = edu self.update_education_list() self.clear_education_form() self.current_edu_index = -1 def remove_education(self): if self.current_edu_index == -1: return self.resume_data[“education”].pop(self.current_edu_index) self.update_education_list() self.clear_education_form() self.current_edu_index = -1 def load_education(self, item): index = self.edu_list.row(item) self.current_edu_index = index edu = self.resume_data[“education”][index] self.edu_school_edit.setText(edu[“school”]) self.edu_degree_edit.setText(edu[“degree”]) self.edu_field_edit.setText(edu[“field”]) self.edu_start_date.setDate(QDate.fromString(edu[“start_date”], “yyyy-MM-dd”)) if edu[“current”]: self.edu_current.setChecked(True) self.edu_end_date.setEnabled(False) else: self.edu_current.setChecked(False) self.edu_end_date.setDate(QDate.fromString(edu[“end_date”], “yyyy-MM-dd”)) self.edu_end_date.setEnabled(True) self.edu_gpa_edit.setText(edu[“gpa”]) self.edu_description.setPlainText(edu[“description”]) def update_education_list(self): self.edu_list.clear() for edu in self.resume_data[“education”]: item = QListWidgetItem(f”{edu[‘degree’]} – {edu[‘school’]}”) self.edu_list.addItem(item) def clear_education_form(self): self.edu_school_edit.clear() self.edu_degree_edit.clear() self.edu_field_edit.clear() self.edu_start_date.setDate(QDate.currentDate()) self.edu_end_date.setDate(QDate.currentDate()) self.edu_current.setChecked(False) self.edu_gpa_edit.clear() self.edu_description.clear() self.edu_end_date.setEnabled(True) def add_experience(self): self.collect_personal_info() exp = { “company”: self.exp_company_edit.text(), “position”: self.exp_position_edit.text(), “start_date”: self.exp_start_date.date().toString(“yyyy-MM-dd”), “end_date”: “” if self.exp_current.isChecked() else self.exp_end_date.date().toString(“yyyy-MM-dd”), “current”: self.exp_current.isChecked(), “description”: self.exp_description.toPlainText() } self.resume_data[“experience”].append(exp) self.update_experience_list() self.clear_experience_form() def update_experience(self): if self.current_exp_index == -1: return exp = { “company”: self.exp_company_edit.text(), “position”: self.exp_position_edit.text(), “start_date”: self.exp_start_date.date().toString(“yyyy-MM-dd”), “end_date”: “” if self.exp_current.isChecked() else self.exp_end_date.date().toString(“yyyy-MM-dd”), “current”: self.exp_current.isChecked(), “description”: self.exp_description.toPlainText() } self.resume_data[“experience”][self.current_exp_index] = exp self.update_experience_list() self.clear_experience_form() self.current_exp_index = -1 def remove_experience(self): if self.current_exp_index == -1: return self.resume_data[“experience”].pop(self.current_exp_index) self.update_experience_list() self.clear_experience_form() self.current_exp_index = -1 def load_experience(self, item): index = self.exp_list.row(item) self.current_exp_index = index exp = self.resume_data[“experience”][index] self.exp_company_edit.setText(exp[“company”]) self.exp_position_edit.setText(exp[“position”]) self.exp_start_date.setDate(QDate.fromString(exp[“start_date”], “yyyy-MM-dd”)) if exp[“current”]: self.exp_current.setChecked(True) self.exp_end_date.setEnabled(False) else: self.exp_current.setChecked(False) self.exp_end_date.setDate(QDate.fromString(exp[“end_date”], “yyyy-MM-dd”)) self.exp_end_date.setEnabled(True) self.exp_description.setPlainText(exp[“description”]) def update_experience_list(self): self.exp_list.clear() for exp in self.resume_data[“experience”]: item = QListWidgetItem(f”{exp[‘position’]} – {exp[‘company’]}”) self.exp_list.addItem(item) def clear_experience_form(self): self.exp_company_edit.clear() self.exp_position_edit.clear() self.exp_start_date.setDate(QDate.currentDate()) self.exp_end_date.setDate(QDate.currentDate()) self.exp_current.setChecked(False) self.exp_description.clear() self.exp_end_date.setEnabled(True) def add_skill(self): skill = f”{self.skill_edit.text()} ({self.skill_level_combo.currentText()})” self.resume_data[“skills”].append(skill) self.update_skills_list() self.skill_edit.clear() def remove_skill(self): for item in self.skill_list.selectedItems(): index = self.skill_list.row(item) self.resume_data[“skills”].pop(index) self.skill_list.takeItem(index) def update_skills_list(self): self.skill_list.clear() for skill in self.resume_data[“skills”]: self.skill_list.addItem(skill) def add_project(self): self.collect_personal_info() proj = { “name”: self.proj_name_edit.text(), “role”: self.proj_role_edit.text(), “start_date”: self.proj_start_date.date().toString(“yyyy-MM-dd”), “end_date”: “” if self.proj_current.isChecked() else self.proj_end_date.date().toString(“yyyy-MM-dd”), “current”: self.proj_current.isChecked(), “url”: self.proj_url_edit.text(), “description”: self.proj_description.toPlainText() } self.resume_data[“projects”].append(proj) self.update_project_list() self.clear_project_form() def update_project(self): if self.current_proj_index == -1: return proj = { “name”: self.proj_name_edit.text(), “role”: self.proj_role_edit.text(), “start_date”: self.proj_start_date.date().toString(“yyyy-MM-dd”), “end_date”: “” if self.proj_current.isChecked() else self.proj_end_date.date().toString(“yyyy-MM-dd”), “current”: self.proj_current.isChecked(), “url”: self.proj_url_edit.text(), “description”: self.proj_description.toPlainText() } self.resume_data[“projects”][self.current_proj_index] = proj self.update_project_list() self.clear_project_form() self.current_proj_index = -1 def remove_project(self): if self.current_proj_index == -1: return self.resume_data[“projects”].pop(self.current_proj_index) self.update_project_list() self.clear_project_form() self.current_proj_index = -1 def load_project(self, item): index = self.proj_list.row(item) self.current_proj_index = index proj = self.resume_data[“projects”][index] self.proj_name_edit.setText(proj[“name”]) self.proj_role_edit.setText(proj[“role”]) self.proj_start_date.setDate(QDate.fromString(proj[“start_date”], “yyyy-MM-dd”)) if proj[“current”]: self.proj_current.setChecked(True) self.proj_end_date.setEnabled(False) else: self.proj_current.setChecked(False) self.proj_end_date.setDate(QDate.fromString(proj[“end_date”], “yyyy-MM-dd”)) self.proj_end_date.setEnabled(True) self.proj_url_edit.setText(proj[“url”]) self.proj_description.setPlainText(proj[“description”]) def update_project_list(self): self.proj_list.clear() for proj in self.resume_data[“projects”]: item = QListWidgetItem(f”{proj[‘name’]} ({proj[‘role’]})”) self.proj_list.addItem(item) def clear_project_form(self): self.proj_name_edit.clear() self.proj_role_edit.clear() self.proj_start_date.setDate(QDate.currentDate()) self.proj_end_date.setDate(QDate.currentDate()) self.proj_current.setChecked(False) self.proj_url_edit.clear() self.proj_description.clear() self.proj_end_date.setEnabled(True) def add_certification(self): self.collect_personal_info() cert = { “name”: self.cert_name_edit.text(), “organization”: self.cert_org_edit.text(), “date”: self.cert_date.date().toString(“yyyy-MM-dd”), “url”: self.cert_url_edit.text() } self.resume_data[“certifications”].append(cert) self.update_certification_list() self.clear_certification_form() def update_certification(self): if self.current_cert_index == -1: return cert = { “name”: self.cert_name_edit.text(), “organization”: self.cert_org_edit.text(), “date”: self.cert_date.date().toString(“yyyy-MM-dd”), “url”: self.cert_url_edit.text() } self.resume_data[“certifications”][self.current_cert_index] = cert self.update_certification_list() self.clear_certification_form() self.current_cert_index = -1 def remove_certification(self): if self.current_cert_index == -1: return self.resume_data[“certifications”].pop(self.current_cert_index) self.update_certification_list() self.clear_certification_form() self.current_cert_index = -1 def load_certification(self, item): index = self.cert_list.row(item) self.current_cert_index = index cert = self.resume_data[“certifications”][index] self.cert_name_edit.setText(cert[“name”]) self.cert_org_edit.setText(cert[“organization”]) self.cert_date.setDate(QDate.fromString(cert[“date”], “yyyy-MM-dd”)) self.cert_url_edit.setText(cert[“url”]) def update_certification_list(self): self.cert_list.clear() for cert in self.resume_data[“certifications”]: item = QListWidgetItem(f”{cert[‘name’]} – {cert[‘organization’]}”) self.cert_list.addItem(item) def clear_certification_form(self): self.cert_name_edit.clear() self.cert_org_edit.clear() self.cert_date.setDate(QDate.currentDate()) self.cert_url_edit.clear() def add_language(self): lang = f”{self.lang_edit.text()} ({self.lang_level_combo.currentText()})” self.resume_data[“languages”].append(lang) self.update_languages_list() self.lang_edit.clear() def remove_language(self): for item in self.lang_list.selectedItems(): index = self.lang_list.row(item) self.resume_data[“languages”].pop(index) self.lang_list.takeItem(index) def update_languages_list(self): self.lang_list.clear() for lang in self.resume_data[“languages”]: self.lang_list.addItem(lang) def preview_resume(self): “””生成简历预览””” self.collect_personal_info() self.collect_summary() preview_text = “=== 简历预览 ===nn” preview_text += “🌟 个人信息:n” preview_text += f”👤 姓名: {self.resume_data[‘personal_info’][‘name’]}n” preview_text += f”✉️ 邮箱: {self.resume_data[‘personal_info’][’email’]}n” preview_text += f”📱 电话: {self.resume_data[‘personal_info’][‘phone’]}n” preview_text += f”🏠 地址: {self.resume_data[‘personal_info’][‘address’]}n” preview_text += f”🔗 LinkedIn: {self.resume_data[‘personal_info’][‘linkedin’]}n” preview_text += f”💻 GitHub: {self.resume_data[‘personal_info’][‘github’]}n” preview_text += f”🌐 个人网站: {self.resume_data[‘personal_info’][‘website’]}nn” preview_text += “📝 职业概述:n” preview_text += f”{self.resume_data[‘summary’]}nn” preview_text += “🎓 教育经历:n” for edu in self.resume_data[“education”]: preview_text += f”- 🎓 {edu[‘degree’]} – {edu[‘school’]} ({edu[‘field’]})n” preview_text += f” 📅 {edu[‘start_date’]} 至 {‘至今’ if edu[‘current’] else edu[‘end_date’]}n” preview_text += f” 📊 GPA: {edu[‘gpa’]}n” preview_text += f” 📋 描述: {edu[‘description’]}nn” preview_text += “💼 工作经历:n” for exp in self.resume_data[“experience”]: preview_text += f”- 💼 {exp[‘position’]} – {exp[‘company’]}n” preview_text += f” 📅 {exp[‘start_date’]} 至 {‘至今’ if exp[‘current’] else exp[‘end_date’]}n” preview_text += f” 📋 描述: {exp[‘description’]}nn” preview_text += “🛠️ 技能:n” for skill in self.resume_data[“skills”]: preview_text += f”- {skill}n” preview_text += “n” preview_text += “📂 项目经历:n” for proj in self.resume_data[“projects”]: preview_text += f”- 📂 {proj[‘name’]} ({proj[‘role’]})n” preview_text += f” 📅 {proj[‘start_date’]} 至 {‘进行中’ if proj[‘current’] else proj[‘end_date’]}n” preview_text += f” 🔗 URL: {proj[‘url’]}n” preview_text += f” 📋 描述: {proj[‘description’]}nn” preview_text += “📜 证书:n” for cert in self.resume_data[“certifications”]: preview_text += f”- 📜 {cert[‘name’]} – {cert[‘organization’]} ({cert[‘date’]})n” preview_text += f” 🔗 URL: {cert[‘url’]}nn” preview_text += “🌐 语言能力:n” for lang in self.resume_data[“languages”]: preview_text += f”- {lang}n” self.preview_text.setPlainText(preview_text) def export_to_pdf(self): self.collect_personal_info() self.collect_summary() # 创建PDF pdf = FPDF() pdf.add_page() pdf.set_auto_page_break(auto=True, margin=15) # 设置字体 pdf.set_font(“Arial”, ‘B’, 16) # 个人信息 pdf.cell(0, 10, self.resume_data[“personal_info”][“name”], 0, 1, ‘C’) pdf.set_font(“Arial”, ”, 12) contact_info = [] if self.resume_data[“personal_info”][“email”]: contact_info.append(self.resume_data[“personal_info”][“email”]) if self.resume_data[“personal_info”][“phone”]: contact_info.append(self.resume_data[“personal_info”][“phone”]) if self.resume_data[“personal_info”][“address”]: contact_info.append(self.resume_data[“personal_info”][“address”]) pdf.cell(0, 10, ” | “.join(contact_info), 0, 1, ‘C’) # 添加链接 links = [] if self.resume_data[“personal_info”][“linkedin”]: links.append(f”LinkedIn: {self.resume_data[‘personal_info’][‘linkedin’]}”) if self.resume_data[“personal_info”][“github”]: links.append(f”GitHub: {self.resume_data[‘personal_info’][‘github’]}”) if self.resume_data[“personal_info”][“website”]: links.append(f”Website: {self.resume_data[‘personal_info’][‘website’]}”) if links: pdf.cell(0, 10, ” | “.join(links), 0, 1, ‘C’) pdf.ln(10) # 职业概述 if self.resume_data[“summary”]: pdf.set_font(“Arial”, ‘B’, 14) pdf.cell(0, 10, “职业概述”, 0, 1, ‘L’) pdf.set_font(“Arial”, ”, 12) pdf.multi_cell(0, 6, self.resume_data[“summary”]) pdf.ln(5) # 教育经历 if self.resume_data[“education”]: pdf.set_font(“Arial”, ‘B’, 14) pdf.cell(0, 10, “教育经历”, 0, 1, ‘L’) pdf.set_font(“Arial”, ”, 12) for edu in self.resume_data[“education”]: pdf.set_font(“Arial”, ‘B’, 12) pdf.cell(0, 6, f”{edu[‘degree’]} – {edu[‘school’]}”, 0, 1, ‘L’) pdf.set_font(“Arial”, ”, 12) date_range = f”{edu[‘start_date’]} – {‘至今’ if edu[‘current’] else edu[‘end_date’]}” if edu[“gpa”]: date_range += f” | GPA: {edu[‘gpa’]}” pdf.cell(0, 6, f”{edu[‘field’]} | {date_range}”, 0, 1, ‘L’) if edu[“description”]: pdf.multi_cell(0, 6, edu[“description”]) pdf.ln(2) # 工作经历 if self.resume_data[“experience”]: pdf.set_font(“Arial”, ‘B’, 14) pdf.cell(0, 10, “工作经历”, 0, 1, ‘L’) pdf.set_font(“Arial”, ”, 12) for exp in self.resume_data[“experience”]: pdf.set_font(“Arial”, ‘B’, 12) pdf.cell(0, 6, f”{exp[‘position’]} – {exp[‘company’]}”, 0, 1, ‘L’) pdf.set_font(“Arial”, ”, 12) pdf.cell(0, 6, f”{exp[‘start_date’]} – {‘至今’ if exp[‘current’] else exp[‘end_date’]}”, 0, 1, ‘L’) if exp[“description”]: pdf.multi_cell(0, 6, exp[“description”]) pdf.ln(2) # 技能 if self.resume_data[“skills”]: pdf.set_font(“Arial”, ‘B’, 14) pdf.cell(0, 10, “技能”, 0, 1, ‘L’) pdf.set_font(“Arial”, ”, 12) skills = “, “.join(self.resume_data[“skills”]) pdf.multi_cell(0, 6, skills) pdf.ln(5) # 项目经历 if self.resume_data[“projects”]: pdf.set_font(“Arial”, ‘B’, 14) pdf.cell(0, 10, “项目经历”, 0, 1, ‘L’) pdf.set_font(“Arial”, ”, 12) for proj in self.resume_data[“projects”]: pdf.set_font(“Arial”, ‘B’, 12) pdf.cell(0, 6, f”{proj[‘name’]} ({proj[‘role’]})”, 0, 1, ‘L’) pdf.set_font(“Arial”, ”, 12) date_range = f”{proj[‘start_date’]} – {‘进行中’ if proj[‘current’] else proj[‘end_date’]}” if proj[“url”]: date_range += f” | URL: {proj[‘url’]}” pdf.cell(0, 6, date_range, 0, 1, ‘L’) if proj[“description”]: pdf.multi_cell(0, 6, proj[“description”]) pdf.ln(2) # 证书 if self.resume_data[“certifications”]: pdf.set_font(“Arial”, ‘B’, 14) pdf.cell(0, 10, “证书”, 0, 1, ‘L’) pdf.set_font(“Arial”, ”, 12) for cert in self.resume_data[“certifications”]: cert_line = f”{cert[‘name’]} – {cert[‘organization’]} ({cert[‘date’]})” if cert[“url”]: cert_line += f” | URL: {cert[‘url’]}” pdf.cell(0, 6, cert_line, 0, 1, ‘L’) pdf.ln(2) # 语言能力 if self.resume_data[“languages”]: pdf.set_font(“Arial”, ‘B’, 14) pdf.cell(0, 10, “语言能力”, 0, 1, ‘L’) pdf.set_font(“Arial”, ”, 12) langs = “, “.join(self.resume_data[“languages”]) pdf.multi_cell(0, 6, langs) # 保存PDF file_path, _ = QFileDialog.getSaveFileName(self, “保存PDF”, “我的简历.pdf”, “PDF文件 (*.pdf)”) if file_path: pdf.output(file_path) QMessageBox.information(self, “成功”, “简历已成功导出为PDF!”) def save_resume_data(self): self.collect_personal_info() self.collect_summary() file_path, _ = QFileDialog.getSaveFileName(self, “保存简历数据”, “resume_data.json”, “JSON文件 (*.json)”) if file_path: with open(file_path, ‘w’, encoding=’utf-8′) as f: json.dump(self.resume_data, f, ensure_ascii=False, indent=4) QMessageBox.information(self, “成功”, “简历数据已保存!”) def load_resume_data(self): file_path, _ = QFileDialog.getOpenFileName(self, “加载简历数据”, “”, “JSON文件 (*.json)”) if file_path: try: with open(file_path, ‘r’, encoding=’utf-8′) as f: self.resume_data = json.load(f) # 更新UI self.update_ui_from_data() QMessageBox.information(self, “成功”, “简历数据已加载!”) except Exception as e: QMessageBox.critical(self, “错误”, f”加载简历数据失败: {str(e)}”) def update_ui_from_data(self): # 个人信息 personal_info = self.resume_data[“personal_info”] self.name_edit.setText(personal_info.get(“name”, “”)) self.email_edit.setText(personal_info.get(“email”, “”)) self.phone_edit.setText(personal_info.get(“phone”, “”)) self.address_edit.setText(personal_info.get(“address”, “”)) self.linkedin_edit.setText(personal_info.get(“linkedin”, “”)) self.github_edit.setText(personal_info.get(“github”, “”)) self.website_edit.setText(personal_info.get(“website”, “”)) # 职业概述 self.summary_edit.setPlainText(self.resume_data.get(“summary”, “”)) # 教育经历 self.update_education_list() # 工作经历 self.update_experience_list() # 技能 self.update_skills_list() # 项目经历 self.update_project_list() # 证书 self.update_certification_list() # 语言能力 self.update_languages_list() if __name__ == “__main__”: app = QApplication(sys.argv) # 设置应用程序样式和字体 app.setStyle(“Fusion”) # 设置调色板 palette = QPalette() palette.setColor(QPalette.Window, QColor(240, 242, 245)) palette.setColor(QPalette.WindowText, QColor(0, 0, 0)) palette.setColor(QPalette.Base, QColor(255, 255, 255)) palette.setColor(QPalette.AlternateBase, QColor(240, 240, 240)) palette.setColor(QPalette.ToolTipBase, QColor(255, 255, 255)) palette.setColor(QPalette.ToolTipText, QColor(0, 0, 0)) palette.setColor(QPalette.Text, QColor(0, 0, 0)) palette.setColor(QPalette.Button, QColor(240, 240, 240)) palette.setColor(QPalette.ButtonText, QColor(0, 0, 0)) palette.setColor(QPalette.BrightText, QColor(255, 0, 0)) palette.setColor(QPalette.Highlight, QColor(76, 175, 80)) palette.setColor(QPalette.HighlightedText, QColor(255, 255, 255)) app.setPalette(palette) # 创建并显示主窗口 window = ResumeGenerator() window.show() sys.exit(app.exec_())
  • 本工具通过PyQt5实现了: 高效管理:比传统文档编辑效率提升300% 专业输出:符合HR系统的解析标准 灵活定制:模块化设计易于扩展 未来可增加: LaTeX导出支持 在线模板市场 AI辅助内容生成 多语言国际化 Q&A环节 Q:如何添加自定义模板? A:在templates目录下新建JSON文件,按照现有模板格式编写样式规则。 Q:程序无法显示中文怎么办? A:确保系统已安装中文字体,并在PDF生成时指定中文字体路径。 Q:能否导出为Word格式? A:当前版本仅支持PDF,可通过python-docx库自行扩展。 相关技术栈推荐 高级功能:PyQtGraph数据可视化 云存储:集成Dropbox API 自动化:结合Selenium实现自动投递 求职小贴士 使用本工具生成简历后,建议: 根据不同岗位调整关键词 保持一页纸原则 量化工作成果 定期更新内容 到此这篇关于Python+PyQt5实现简历自动生成工具的文章就介绍到这了,更多相关Python自动生成简历内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: python简单实现刷新智联简历 使用C# CefSharp Python采集某网站简历并且自动发送邀请短信的方法 python+selenium实现简历自动刷新的示例代码 Python实现提取PDF简历信息并存入Excel Python Word文件自动化实战之简历筛选 利用Python实现自动生成数据日报 Python办公自动化之数据可视化与报表生成 python使用MkDocs自动生成文档的操作方法
  • 目录
    • 一、概述:为什么需要自动化简历工具
    • 二、功能全景图
      • 2.1 核心功能模块
      • 2.2 特色功能
    • 三、效果展示
      • 四、开发步骤详解
        • 4.1 环境配置
        • 4.2 核心类设计
        • 4.3 数据管理机制
      • 五、关键代码解析
        • 5.1 动态表单管理
        • 5.2 PDF生成引擎
        • 5.3 样式管理系统
      • 六、完整源码下载
        • 七、总结与展望

          在当今竞争激烈的求职市场中,一份专业、规范的简历是获得面试机会的关键。然而,手动编写和排版简历往往耗时费力,特别是当我们需要针对不同职位定制多份简历时。本文介绍的基于PyQt5的自动化简历生成工具,将彻底改变这一现状。

          该工具具有以下核心优势:

          • 一站式管理:整合个人信息、教育背景、工作经历等所有模块
          • 可视化编辑:直观的GUI界面,告别代码和命令行
          • 多格式输出:支持PDF导出,确保跨平台兼容性
          • 数据持久化:JSON格式保存/加载,简历数据永不丢失
          • 模板化设计:多种风格模板满足不同行业需求

          模块名称 功能描述 技术实现
          个人信息 收集基础联系方式和社交资料 QLineEdit + QFormLayout
          教育经历 管理学历、专业、GPA等信息 QListWidget + 动态表单
          工作经历 记录职位、公司、工作描述 日期控件 + 富文本编辑
          技能专长 分类展示技术栈和熟练度 QComboBox + 层级列表
          项目作品 展示项目成果和贡献 超链接支持 + 多行文本
          证书资质 管理专业认证信息 时间选择器 + URL字段
          语言能力 多语言水平标注 等级选择器

          • 实时预览:所见即所得的简历预览功能
          • 智能日期:"至今"选项自动处理日期显示
          • 响应式布局:自适应不同屏幕尺寸
          • 主题配色:多套可视化主题随时切换
          • 数据校验:关键字段自动验证提醒

          UI界面概览

          左侧为标签式编辑面板,右侧为实时预览区,符合专业软件设计范式。

          pip install PyQt5 fpdf
          

          class ResumeGenerator(QMainWindow):
              def __init__(self):
                  super().__init__()
                  # 初始化UI和数据
                  self.init_ui()
                  self.init_resume_data()
                  
              def init_ui(self):
                  # 创建主窗口布局
                  self.setup_main_window()
                  self.add_personal_info_tab()
                  self.add_education_tab()
                  # ...其他标签页
                  self.setup_preview_panel()
          

          采用三层架构设计:

          • 表示层:PyQt5界面组件
          • 逻辑层:简历数据处理方法
          • 持久层:JSON序列化存储

          教育/工作经历采用列表+详情表单的交互模式:

          def add_education(self):
              edu = {
                  "school": self.edu_school_edit.text(),
                  "degree": self.edu_degree_edit.text(),
                  # 其他字段...
              }
              self.resume_data["education"].append(edu)
              self.update_education_list()
          

          基于FPDF库的定制化输出:

          def export_to_pdf(self):
              pdf = FPDF()
              pdf.add_page()
              # 设置中文字体支持
              pdf.add_font('SimSun', '', 'simsun.ttc', uni=True)
              
              # 添加内容区块
              self.add_personal_section(pdf)
              self.add_education_section(pdf)
              # ...其他部分
              
              pdf.output("resume.pdf")
          

          使用Qt样式表实现现代化UI:

          self.setStyleSheet("""
              QMainWindow {
                  background-color: #f0f2f5;
              }
              QTabBar::tab {
                  padding: 10px;
                  border-radius: 5px;
              }
              QPushButton {
                  background-color: #4CAF50;
                  color: white;
              }
          """)
          

          import sys
          import json
          import os
          from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, 
                                      QLabel, QLineEdit, QTextEdit, QPushButton, QComboBox, 
                                      QListWidget, QListWidgetItem, QTabWidget, QFileDialog, 
                                      QMessageBox, QFormLayout, QSpinBox, QDateEdit, QCheckBox,
                                      QGroupBox, QFrame)
          from PyQt5.QtCore import Qt, QDate
          from PyQt5.QtGui import QFont, QIcon, QColor, QPalette
          from fpdf import FPDF
          from datetime import datetime
          
          class ResumeGenerator(QMainWindow):
              def __init__(self):
                  super().__init__()
                  self.setWindowTitle("自动化简历生成工具")
                  self.setGeometry(100, 100, 1000, 750)
                  
                  # 尝试加载图标,如果失败则忽略
                  try:
                      self.setWindowIcon(QIcon("resume_icon.png"))
                  except:
                      pass
                  
                  # 初始化UI
                  self.init_ui()
                  
                  # 加载模板
                  self.load_templates()
                  
                  # 初始化简历数据结构
                  self.init_resume_data()
                  
                  # 当前编辑的项目索引
                  self.current_edu_index = -1
                  self.current_exp_index = -1
                  self.current_proj_index = -1
                  self.current_cert_index = -1
                  
              def init_ui(self):
                  # 设置主窗口背景和全局样式
                  self.setStyleSheet("""
                      QMainWindow {
                          background-color: #f0f2f5;
                      }
                      QTabBar::tab {
                          padding: 10px;
                          border-top-left-radius: 5px;
                          border-top-right-radius: 5px;
                          margin-right: 2px;
                      }
                      QTabBar::tab:selected {
                          background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                              stop:0 #ffffff, stop:1 #e0e0e0);
                          border-bottom: 2px solid #4CAF50;
                      }
                      QTabBar::tab:!selected {
                          background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                              stop:0 #e0e0e0, stop:1 #d0d0d0);
                      }
                      QLineEdit, QTextEdit, QComboBox, QSpinBox, QDateEdit {
                          padding: 8px;
                          border: 1px solid #ddd;
                          border-radius: 4px;
                          background: white;
                      }
                      QTextEdit {
                          min-height: 100px;
                      }
                      QListWidget {
                          border: 1px solid #ddd;
                          background: white;
                          border-radius: 4px;
                      }
                      QPushButton {
                          padding: 8px 12px;
                          border-radius: 4px;
                          font-weight: bold;
                          min-width: 80px;
                      }
                      QGroupBox {
                          border: 1px solid #ddd;
                          border-radius: 5px;
                          margin-top: 10px;
                          padding-top: 15px;
                          background: white;
                      }
                      QGroupBox::title {
                          subcontrol-origin: margin;
                          left: 10px;
                          padding: 0 3px;
                      }
                  """)
                  
                  # 主窗口布局
                  main_widget = QWidget()
                  self.setCentralWidget(main_widget)
                  
                  main_layout = QHBoxLayout()
                  main_widget.setLayout(main_layout)
                  main_layout.setContentsMargins(10, 10, 10, 10)
                  main_layout.setSpacing(15)
                  
                  # 左侧面板 - 简历内容编辑 (70%宽度)
                  self.left_panel = QTabWidget()
                  self.left_panel.setTabPosition(QTabWidget.North)
                  self.left_panel.setDocumentMode(True)
                  main_layout.addWidget(self.left_panel, 7)
                  
                  # 右侧面板 - 预览和操作 (30%宽度)
                  right_panel = QWidget()
                  right_panel.setMaximumWidth(350)
                  right_layout = QVBoxLayout()
                  right_layout.setContentsMargins(5, 5, 5, 5)
                  right_panel.setLayout(right_layout)
                  main_layout.addWidget(right_panel, 3)
                  
                  # 添加标签页
                  self.add_personal_info_tab()
                  self.add_summary_tab()
                  self.add_education_tab()
                  self.add_experience_tab()
                  self.add_skills_tab()
                  self.add_projects_tab()
                  self.add_certifications_tab()
                  self.add_languages_tab()
                  
                  # 右侧面板内容
                  # 模板选择组
                  template_group = QGroupBox("简历模板")
                  template_layout = QVBoxLayout()
                  template_group.setLayout(template_layout)
                  
                  self.template_combo = QComboBox()
                  self.template_combo.setStyleSheet("""
                      QComboBox {
                          padding: 8px;
                          border: 1px solid #4CAF50;
                          border-radius: 4px;
                          background: white;
                      }
                      QComboBox::drop-down {
                          border: none;
                      }
                  """)
                  template_layout.addWidget(self.template_combo)
                  
                  # 操作按钮组
                  button_group = QGroupBox("操作")
                  button_layout = QVBoxLayout()
                  button_group.setLayout(button_layout)
                  
                  # 预览按钮
                  self.preview_btn = QPushButton("📄 预览简历")
                  self.preview_btn.setStyleSheet("""
                      QPushButton {
                          background-color: #4CAF50;
                          color: white;
                      }
                      QPushButton:hover {
                          background-color: #45a049;
                      }
                  """)
                  self.preview_btn.clicked.connect(self.preview_resume)
                  button_layout.addWidget(self.preview_btn)
                  
                  # 导出按钮
                  self.export_btn = QPushButton("💾 导出PDF")
                  self.export_btn.setStyleSheet("""
                      QPushButton {
                          background-color: #2196F3;
                          color: white;
                      }
                      QPushButton:hover {
                          background-color: #0b7dda;
                      }
                  """)
                  self.export_btn.clicked.connect(self.export_to_pdf)
                  button_layout.addWidget(self.export_btn)
                  
                  # 分隔线
                  line = QFrame()
                  line.setFrameShape(QFrame.HLine)
                  line.setFrameShadow(QFrame.Sunken)
                  button_layout.addWidget(line)
                  
                  # 保存按钮
                  self.save_btn = QPushButton("💾 保存数据")
                  self.save_btn.setStyleSheet("""
                      QPushButton {
                          background-color: #FF9800;
                          color: white;
                      }
                      QPushButton:hover {
                          background-color: #e68a00;
                      }
                  """)
                  self.save_btn.clicked.connect(self.save_resume_data)
                  button_layout.addWidget(self.save_btn)
                  
                  # 加载按钮
                  self.load_btn = QPushButton("📂 加载数据")
                  self.load_btn.setStyleSheet("""
                      QPushButton {
                          background-color: #9C27B0;
                          color: white;
                      }
                      QPushButton:hover {
                          background-color: #7b1fa2;
                      }
                  """)
                  self.load_btn.clicked.connect(self.load_resume_data)
                  button_layout.addWidget(self.load_btn)
                  
                  # 预览区域组
                  preview_group = QGroupBox("简历预览")
                  preview_layout = QVBoxLayout()
                  preview_group.setLayout(preview_layout)
                  
                  self.preview_text = QTextEdit()
                  self.preview_text.setReadOnly(True)
                  self.preview_text.setStyleSheet("""
                      QTextEdit {
                          background-color: #f9f9f9;
                          border: 1px solid #ddd;
                          border-radius: 4px;
                      }
                  """)
                  preview_layout.addWidget(self.preview_text)
                  
                  # 添加到右侧面板
                  right_layout.addWidget(template_group)
                  right_layout.addWidget(button_group)
                  right_layout.addWidget(preview_group)
                  
                  # 设置标签页颜色
                  self.set_tab_colors()
              
              def set_tab_colors(self):
              #为每个标签页设置不同的颜色
                tab_colors = [
                  ("#FF5252", "#FFFFFF"),  # 红色
                  ("#FF9800", "#FFFFFF"),  # 橙色
                  ("#FFEB3B", "#000000"),  # 黄色
                  ("#4CAF50", "#FFFFFF"),  # 绿色
                  ("#2196F3", "#FFFFFF"),  # 蓝色
                  ("#673AB7", "#FFFFFF"),  # 深紫色
                  ("#E91E63", "#FFFFFF"),  # 粉色
                  ("#607D8B", "#FFFFFF")   # 蓝灰色
              ]
              
              # 方法1:统一设置QTabBar样式(推荐)
                tab_bar = self.left_panel.tabBar()
                tab_bar.setStyleSheet("""
                  QTabBar::tab {
                      padding: 10px;
                      border-top-left-radius: 5px;
                      border-top-right-radius: 5px;
                      margin-right: 2px;
                  }
                  QTabBar::tab:selected {
                      background: white;
                      border-bottom: 2px solid #4CAF50;
                  }
                  QTabBar::tab:!selected {
                      background: #e0e0e0;
                  }
              """)
              
              def init_resume_data(self):
                  """初始化简历数据结构"""
                  self.resume_data = {
                      "personal_info": {
                          "name": "",
                          "email": "",
                          "phone": "",
                          "address": "",
                          "linkedin": "",
                          "github": "",
                          "website": ""
                      },
                      "summary": "",
                      "education": [],
                      "experience": [],
                      "skills": [],
                      "projects": [],
                      "certifications": [],
                      "languages": []
                  }
              
              def add_personal_info_tab(self):
                  tab = QWidget()
                  layout = QVBoxLayout()
                  tab.setLayout(layout)
                  
                  # 使用GroupBox组织内容
                  group = QGroupBox("个人信息")
                  form_layout = QFormLayout()
                  group.setLayout(form_layout)
                  
                  # 创建带图标的输入字段
                  self.name_edit = self.create_line_edit("👤", "姓名")
                  self.email_edit = self.create_line_edit("✉️", "邮箱")
                  self.phone_edit = self.create_line_edit("📱", "电话")
                  self.address_edit = self.create_line_edit("🏠", "地址")
                  self.linkedin_edit = self.create_line_edit("🔗", "LinkedIn")
                  self.github_edit = self.create_line_edit("💻", "GitHub")
                  self.website_edit = self.create_line_edit("🌐", "个人网站")
                  
                  # 添加到表单
                  form_layout.addRow("姓名:", self.name_edit)
                  form_layout.addRow("邮箱:", self.email_edit)
                  form_layout.addRow("电话:", self.phone_edit)
                  form_layout.addRow("地址:", self.address_edit)
                  form_layout.addRow("LinkedIn:", self.linkedin_edit)
                  form_layout.addRow("GitHub:", self.github_edit)
                  form_layout.addRow("个人网站:", self.website_edit)
                  
                  layout.addWidget(group)
                  layout.addStretch()
                  
                  self.left_panel.addTab(tab, "个人信息")
              
              def create_line_edit(self, icon, placeholder):
                  """创建带样式的QLineEdit"""
                  line_edit = QLineEdit()
                  line_edit.setPlaceholderText(f"{icon} {placeholder}")
                  line_edit.setStyleSheet("""
                      QLineEdit {
                          padding: 10px;
                          border: 1px solid #ddd;
                          border-radius: 5px;
                          font-size: 14px;
                      }
                      QLineEdit:focus {
                          border: 1px solid #4CAF50;
                      }
                  """)
                  return line_edit
              
              def add_summary_tab(self):
                  tab = QWidget()
                  layout = QVBoxLayout()
                  tab.setLayout(layout)
                  
                  group = QGroupBox("职业概述")
                  group_layout = QVBoxLayout()
                  group.setLayout(group_layout)
                  
                  self.summary_edit = QTextEdit()
                  self.summary_edit.setPlaceholderText("在这里输入你的职业概述...")
                  self.summary_edit.setStyleSheet("""
                      QTextEdit {
                          padding: 10px;
                          border: 1px solid #ddd;
                          border-radius: 5px;
                          font-size: 14px;
                      }
                      QTextEdit:focus {
                          border: 1px solid #2196F3;
                      }
                  """)
                  
                  group_layout.addWidget(self.summary_edit)
                  layout.addWidget(group)
                  layout.addStretch()
                  
                  self.left_panel.addTab(tab, "职业概述")
              
              def add_education_tab(self):
                  tab = QWidget()
                  layout = QVBoxLayout()
                  tab.setLayout(layout)
                  
                  # 教育经历表单组
                  form_group = QGroupBox("添加/编辑教育经历")
                  form_layout = QFormLayout()
                  form_group.setLayout(form_layout)
                  
                  # 创建输入字段
                  self.edu_school_edit = self.create_line_edit("🏫", "学校名称")
                  self.edu_degree_edit = self.create_line_edit("🎓", "学位")
                  self.edu_field_edit = self.create_line_edit("📚", "专业")
                  self.edu_start_date = QDateEdit()
                  self.edu_end_date = QDateEdit()
                  self.edu_current = QCheckBox("至今")
                  self.edu_gpa_edit = self.create_line_edit("📊", "GPA")
                  self.edu_description = QTextEdit()
                  
                  # 设置日期控件
                  self.edu_start_date.setCalendarPopup(True)
                  self.edu_end_date.setCalendarPopup(True)
                  self.edu_current.stateChanged.connect(self.toggle_edu_end_date)
                  
                  # 添加到表单
                  form_layout.addRow("学校:", self.edu_school_edit)
                  form_layout.addRow("学位:", self.edu_degree_edit)
                  form_layout.addRow("专业:", self.edu_field_edit)
                  form_layout.addRow("开始日期:", self.edu_start_date)
                  form_layout.addRow("结束日期:", self.edu_end_date)
                  form_layout.addRow(self.edu_current)
                  form_layout.addRow("GPA:", self.edu_gpa_edit)
                  form_layout.addRow("描述:", self.edu_description)
                  
                  # 按钮布局
                  btn_layout = QHBoxLayout()
                  self.add_edu_btn = self.create_button("➕ 添加", "#4CAF50")
                  self.add_edu_btn.clicked.connect(self.add_education)
                  self.update_edu_btn = self.create_button("🔄 更新", "#2196F3")
                  self.update_edu_btn.clicked.connect(self.update_education)
                  self.remove_edu_btn = self.create_button("❌ 删除", "#F44336")
                  self.remove_edu_btn.clicked.connect(self.remove_education)
                  
                  btn_layout.addWidget(self.add_edu_btn)
                  btn_layout.addWidget(self.update_edu_btn)
                  btn_layout.addWidget(self.remove_edu_btn)
                  
                  # 教育经历列表组
                  list_group = QGroupBox("教育经历列表")
                  list_layout = QVBoxLayout()
                  list_group.setLayout(list_layout)
                  
                  self.edu_list = QListWidget()
                  self.edu_list.itemClicked.connect(self.load_education)
                  self.edu_list.setStyleSheet("""
                      QListWidget {
                          font-size: 14px;
                      }
                      QListWidget::item {
                          padding: 8px;
                          border-bottom: 1px solid #eee;
                      }
                      QListWidget::item:hover {
                          background-color: #f0f0f0;
                      }
                      QListWidget::item:selected {
                          background-color: #e3f2fd;
                          color: #000;
                      }
                  """)
                  
                  list_layout.addWidget(self.edu_list)
                  
                  # 添加到主布局
                  layout.addWidget(form_group)
                  layout.addLayout(btn_layout)
                  layout.addWidget(list_group)
                  
                  self.left_panel.addTab(tab, "教育经历")
              
              def create_button(self, text, color):
                  """创建带样式的按钮"""
                  btn = QPushButton(text)
                  btn.setStyleSheet(f"""
                      QPushButton {{
                          background-color: {color};
                          color: white;
                          padding: 8px 12px;
                          border-radius: 4px;
                          font-weight: bold;
                      }}
                      QPushButton:hover {{
                          background-color: {self.darken_color(color)};
                      }}
                  """)
                  return btn
              
              def darken_color(self, hex_color, factor=0.8):
                  """使颜色变暗"""
                  color = QColor(hex_color)
                  return color.darker(int(1/factor*100)).name()
              
              def add_experience_tab(self):
                  tab = QWidget()
                  layout = QVBoxLayout()
                  tab.setLayout(layout)
                  
                  form_group = QGroupBox("添加/编辑工作经历")
                  form_layout = QFormLayout()
                  form_group.setLayout(form_layout)
                  
                  self.exp_company_edit = self.create_line_edit("🏢", "公司名称")
                  self.exp_position_edit = self.create_line_edit("💼", "职位")
                  self.exp_start_date = QDateEdit()
                  self.exp_end_date = QDateEdit()
                  self.exp_current = QCheckBox("至今")
                  self.exp_description = QTextEdit()
                  
                  self.exp_start_date.setCalendarPopup(True)
                  self.exp_end_date.setCalendarPopup(True)
                  self.exp_current.stateChanged.connect(self.toggle_exp_end_date)
                  
                  form_layout.addRow("公司:", self.exp_company_edit)
                  form_layout.addRow("职位:", self.exp_position_edit)
                  form_layout.addRow("开始日期:", self.exp_start_date)
                  form_layout.addRow("结束日期:", self.exp_end_date)
                  form_layout.addRow(self.exp_current)
                  form_layout.addRow("描述:", self.exp_description)
                  
                  btn_layout = QHBoxLayout()
                  self.add_exp_btn = self.create_button("➕ 添加", "#4CAF50")
                  self.add_exp_btn.clicked.connect(self.add_experience)
                  self.update_exp_btn = self.create_button("🔄 更新", "#2196F3")
                  self.update_exp_btn.clicked.connect(self.update_experience)
                  self.remove_exp_btn = self.create_button("❌ 删除", "#F44336")
                  self.remove_exp_btn.clicked.connect(self.remove_experience)
                  
                  btn_layout.addWidget(self.add_exp_btn)
                  btn_layout.addWidget(self.update_exp_btn)
                  btn_layout.addWidget(self.remove_exp_btn)
                  
                  list_group = QGroupBox("工作经历列表")
                  list_layout = QVBoxLayout()
                  list_group.setLayout(list_layout)
                  
                  self.exp_list = QListWidget()
                  self.exp_list.itemClicked.connect(self.load_experience)
                  list_layout.addWidget(self.exp_list)
                  
                  layout.addWidget(form_group)
                  layout.addLayout(btn_layout)
                  layout.addWidget(list_group)
                  
                  self.left_panel.addTab(tab, "工作经历")
              
              def add_skills_tab(self):
                  tab = QWidget()
                  layout = QVBoxLayout()
                  tab.setLayout(layout)
                  
                  form_group = QGroupBox("添加技能")
                  form_layout = QVBoxLayout()
                  form_group.setLayout(form_layout)
                  
                  skill_layout = QHBoxLayout()
                  self.skill_edit = self.create_line_edit("🔧", "技能名称")
                  self.skill_level_combo = QComboBox()
                  self.skill_level_combo.addItems(["初级", "中级", "高级", "专家"])
                  
                  skill_layout.addWidget(self.skill_edit)
                  skill_layout.addWidget(self.skill_level_combo)
                  
                  btn_layout = QHBoxLayout()
                  self.add_skill_btn = self.create_button("➕ 添加技能", "#4CAF50")
                  self.add_skill_btn.clicked.connect(self.add_skill)
                  self.remove_skill_btn = self.create_button("❌ 删除选中", "#F44336")
                  self.remove_skill_btn.clicked.connect(self.remove_skill)
                  
                  btn_layout.addWidget(self.add_skill_btn)
                  btn_layout.addWidget(self.remove_skill_btn)
                  
                  list_group = QGroupBox("技能列表")
                  list_layout = QVBoxLayout()
                  list_group.setLayout(list_layout)
                  
                  self.skill_list = QListWidget()
                  list_layout.addWidget(self.skill_list)
                  
                  form_layout.addWidget(QLabel("添加技能:"))
                  form_layout.addLayout(skill_layout)
                  form_layout.addLayout(btn_layout)
                  
                  layout.addWidget(form_group)
                  layout.addWidget(list_group)
                  
                  self.left_panel.addTab(tab, "技能")
              
              def add_projects_tab(self):
                  tab = QWidget()
                  layout = QVBoxLayout()
                  tab.setLayout(layout)
                  
                  form_group = QGroupBox("添加/编辑项目")
                  form_layout = QFormLayout()
                  form_group.setLayout(form_layout)
                  
                  self.proj_name_edit = self.create_line_edit("📂", "项目名称")
                  self.proj_role_edit = self.create_line_edit("👤", "你的角色")
                  self.proj_start_date = QDateEdit()
                  self.proj_end_date = QDateEdit()
                  self.proj_current = QCheckBox("进行中")
                  self.proj_description = QTextEdit()
                  self.proj_url_edit = self.create_line_edit("🔗", "项目URL")
                  
                  self.proj_start_date.setCalendarPopup(True)
                  self.proj_end_date.setCalendarPopup(True)
                  self.proj_current.stateChanged.connect(self.toggle_proj_end_date)
                  
                  form_layout.addRow("项目名称:", self.proj_name_edit)
                  form_layout.addRow("你的角色:", self.proj_role_edit)
                  form_layout.addRow("开始日期:", self.proj_start_date)
                  form_layout.addRow("结束日期:", self.proj_end_date)
                  form_layout.addRow(self.proj_current)
                  form_layout.addRow("项目URL:", self.proj_url_edit)
                  form_layout.addRow("描述:", self.proj_description)
                  
                  btn_layout = QHBoxLayout()
                  self.add_proj_btn = self.create_button("➕ 添加", "#4CAF50")
                  self.add_proj_btn.clicked.connect(self.add_project)
                  self.update_proj_btn = self.create_button("🔄 更新", "#2196F3")
                  self.update_proj_btn.clicked.connect(self.update_project)
                  self.remove_proj_btn = self.create_button("❌ 删除", "#F44336")
                  self.remove_proj_btn.clicked.connect(self.remove_project)
                  
                  btn_layout.addWidget(self.add_proj_btn)
                  btn_layout.addWidget(self.update_proj_btn)
                  btn_layout.addWidget(self.remove_proj_btn)
                  
                  list_group = QGroupBox("项目列表")
                  list_layout = QVBoxLayout()
                  list_group.setLayout(list_layout)
                  
                  self.proj_list = QListWidget()
                  self.proj_list.itemClicked.connect(self.load_project)
                  list_layout.addWidget(self.proj_list)
                  
                  layout.addWidget(form_group)
                  layout.addLayout(btn_layout)
                  layout.addWidget(list_group)
                  
                  self.left_panel.addTab(tab, "项目经历")
              
              def add_certifications_tab(self):
                  tab = QWidget()
                  layout = QVBoxLayout()
                  tab.setLayout(layout)
                  
                  form_group = QGroupBox("添加/编辑证书")
                  form_layout = QFormLayout()
                  form_group.setLayout(form_layout)
                  
                  self.cert_name_edit = self.create_line_edit("📜", "证书名称")
                  self.cert_org_edit = self.create_line_edit("🏛️", "颁发机构")
                  self.cert_date = QDateEdit()
                  self.cert_url_edit = self.create_line_edit("🔗", "证书URL")
                  
                  self.cert_date.setCalendarPopup(True)
                  
                  form_layout.addRow("证书名称:", self.cert_name_edit)
                  form_layout.addRow("颁发机构:", self.cert_org_edit)
                  form_layout.addRow("获得日期:", self.cert_date)
                  form_layout.addRow("证书URL:", self.cert_url_edit)
                  
                  btn_layout = QHBoxLayout()
                  self.add_cert_btn = self.create_button("➕ 添加", "#4CAF50")
                  self.add_cert_btn.clicked.connect(self.add_certification)
                  self.update_cert_btn = self.create_button("🔄 更新", "#2196F3")
                  self.update_cert_btn.clicked.connect(self.update_certification)
                  self.remove_cert_btn = self.create_button("❌ 删除", "#F44336")
                  self.remove_cert_btn.clicked.connect(self.remove_certification)
                  
                  btn_layout.addWidget(self.add_cert_btn)
                  btn_layout.addWidget(self.update_cert_btn)
                  btn_layout.addWidget(self.remove_cert_btn)
                  
                  list_group = QGroupBox("证书列表")
                  list_layout = QVBoxLayout()
                  list_group.setLayout(list_layout)
                  
                  self.cert_list = QListWidget()
                  self.cert_list.itemClicked.connect(self.load_certification)
                  list_layout.addWidget(self.cert_list)
                  
                  layout.addWidget(form_group)
                  layout.addLayout(btn_layout)
                  layout.addWidget(list_group)
                  
                  self.left_panel.addTab(tab, "证书")
              
              def add_languages_tab(self):
                  tab = QWidget()
                  layout = QVBoxLayout()
                  tab.setLayout(layout)
                  
                  form_group = QGroupBox("添加语言")
                  form_layout = QVBoxLayout()
                  form_group.setLayout(form_layout)
                  
                  lang_layout = QHBoxLayout()
                  self.lang_edit = self.create_line_edit("🌐", "语言")
                  self.lang_level_combo = QComboBox()
                  self.lang_level_combo.addItems(["初级", "中级", "高级", "母语"])
                  
                  lang_layout.addWidget(self.lang_edit)
                  lang_layout.addWidget(self.lang_level_combo)
                  
                  btn_layout = QHBoxLayout()
                  self.add_lang_btn = self.create_button("➕ 添加语言", "#4CAF50")
                  self.add_lang_btn.clicked.connect(self.add_language)
                  self.remove_lang_btn = self.create_button("❌ 删除选中", "#F44336")
                  self.remove_lang_btn.clicked.connect(self.remove_language)
                  
                  btn_layout.addWidget(self.add_lang_btn)
                  btn_layout.addWidget(self.remove_lang_btn)
                  
                  list_group = QGroupBox("语言列表")
                  list_layout = QVBoxLayout()
                  list_group.setLayout(list_layout)
                  
                  self.lang_list = QListWidget()
                  list_layout.addWidget(self.lang_list)
                  
                  form_layout.addWidget(QLabel("添加语言:"))
                  form_layout.addLayout(lang_layout)
                  form_layout.addLayout(btn_layout)
                  
                  layout.addWidget(form_group)
                  layout.addWidget(list_group)
                  
                  self.left_panel.addTab(tab, "语言能力")
              
              def toggle_edu_end_date(self, state):
                  self.edu_end_date.setEnabled(not bool(state))
              
              def toggle_exp_end_date(self, state):
                  self.exp_end_date.setEnabled(not bool(state))
              
              def toggle_proj_end_date(self, state):
                  self.proj_end_date.setEnabled(not bool(state))
              
              def load_templates(self):
                  """加载简历模板"""
                  templates = [
                      "🌈 多彩创意模板",
                      "💼 专业商务模板",
                      "👔 传统经典模板",
                      "🎨 现代简约模板",
                      "📊 数据分析师模板",
                      "💻 开发者模板",
                      "🎓 学术模板",
                      "✏️ 设计师模板"
                  ]
                  self.template_combo.addItems(templates)
              
              def collect_personal_info(self):
                  self.resume_data["personal_info"] = {
                      "name": self.name_edit.text(),
                      "email": self.email_edit.text(),
                      "phone": self.phone_edit.text(),
                      "address": self.address_edit.text(),
                      "linkedin": self.linkedin_edit.text(),
                      "github": self.github_edit.text(),
                      "website": self.website_edit.text()
                  }
              
              def collect_summary(self):
                  self.resume_data["summary"] = self.summary_edit.toPlainText()
              
              def add_education(self):
                  self.collect_personal_info()
                  
                  edu = {
                      "school": self.edu_school_edit.text(),
                      "degree": self.edu_degree_edit.text(),
                      "field": self.edu_field_edit.text(),
                      "start_date": self.edu_start_date.date().toString("yyyy-MM-dd"),
                      "end_date": "" if self.edu_current.isChecked() else self.edu_end_date.date().toString("yyyy-MM-dd"),
                      "current": self.edu_current.isChecked(),
                      "gpa": self.edu_gpa_edit.text(),
                      "description": self.edu_description.toPlainText()
                  }
                  
                  self.resume_data["education"].append(edu)
                  self.update_education_list()
                  self.clear_education_form()
              
              def update_education(self):
                  if self.current_edu_index == -1:
                      return
                      
                  edu = {
                      "school": self.edu_school_edit.text(),
                      "degree": self.edu_degree_edit.text(),
                      "field": self.edu_field_edit.text(),
                      "start_date": self.edu_start_date.date().toString("yyyy-MM-dd"),
                      "end_date": "" if self.edu_current.isChecked() else self.edu_end_date.date().toString("yyyy-MM-dd"),
                      "current": self.edu_current.isChecked(),
                      "gpa": self.edu_gpa_edit.text(),
                      "description": self.edu_description.toPlainText()
                  }
                  
                  self.resume_data["education"][self.current_edu_index] = edu
                  self.update_education_list()
                  self.clear_education_form()
                  self.current_edu_index = -1
              
              def remove_education(self):
                  if self.current_edu_index == -1:
                      return
                      
                  self.resume_data["education"].pop(self.current_edu_index)
                  self.update_education_list()
                  self.clear_education_form()
                  self.current_edu_index = -1
              
              def load_education(self, item):
                  index = self.edu_list.row(item)
                  self.current_edu_index = index
                  edu = self.resume_data["education"][index]
                  
                  self.edu_school_edit.setText(edu["school"])
                  self.edu_degree_edit.setText(edu["degree"])
                  self.edu_field_edit.setText(edu["field"])
                  self.edu_start_date.setDate(QDate.fromString(edu["start_date"], "yyyy-MM-dd"))
                  
                  if edu["current"]:
                      self.edu_current.setChecked(True)
                      self.edu_end_date.setEnabled(False)
                  else:
                      self.edu_current.setChecked(False)
                      self.edu_end_date.setDate(QDate.fromString(edu["end_date"], "yyyy-MM-dd"))
                      self.edu_end_date.setEnabled(True)
                  
                  self.edu_gpa_edit.setText(edu["gpa"])
                  self.edu_description.setPlainText(edu["description"])
              
              def update_education_list(self):
                  self.edu_list.clear()
                  for edu in self.resume_data["education"]:
                      item = QListWidgetItem(f"{edu['degree']} - {edu['school']}")
                      self.edu_list.addItem(item)
              
              def clear_education_form(self):
                  self.edu_school_edit.clear()
                  self.edu_degree_edit.clear()
                  self.edu_field_edit.clear()
                  self.edu_start_date.setDate(QDate.currentDate())
                  self.edu_end_date.setDate(QDate.currentDate())
                  self.edu_current.setChecked(False)
                  self.edu_gpa_edit.clear()
                  self.edu_description.clear()
                  self.edu_end_date.setEnabled(True)
              
              def add_experience(self):
                  self.collect_personal_info()
                  
                  exp = {
                      "company": self.exp_company_edit.text(),
                      "position": self.exp_position_edit.text(),
                      "start_date": self.exp_start_date.date().toString("yyyy-MM-dd"),
                      "end_date": "" if self.exp_current.isChecked() else self.exp_end_date.date().toString("yyyy-MM-dd"),
                      "current": self.exp_current.isChecked(),
                      "description": self.exp_description.toPlainText()
                  }
                  
                  self.resume_data["experience"].append(exp)
                  self.update_experience_list()
                  self.clear_experience_form()
              
              def update_experience(self):
                  if self.current_exp_index == -1:
                      return
                      
                  exp = {
                      "company": self.exp_company_edit.text(),
                      "position": self.exp_position_edit.text(),
                      "start_date": self.exp_start_date.date().toString("yyyy-MM-dd"),
                      "end_date": "" if self.exp_current.isChecked() else self.exp_end_date.date().toString("yyyy-MM-dd"),
                      "current": self.exp_current.isChecked(),
                      "description": self.exp_description.toPlainText()
                  }
                  
                  self.resume_data["experience"][self.current_exp_index] = exp
                  self.update_experience_list()
                  self.clear_experience_form()
                  self.current_exp_index = -1
              
              def remove_experience(self):
                  if self.current_exp_index == -1:
                      return
                      
                  self.resume_data["experience"].pop(self.current_exp_index)
                  self.update_experience_list()
                  self.clear_experience_form()
                  self.current_exp_index = -1
              
              def load_experience(self, item):
                  index = self.exp_list.row(item)
                  self.current_exp_index = index
                  exp = self.resume_data["experience"][index]
                  
                  self.exp_company_edit.setText(exp["company"])
                  self.exp_position_edit.setText(exp["position"])
                  self.exp_start_date.setDate(QDate.fromString(exp["start_date"], "yyyy-MM-dd"))
                  
                  if exp["current"]:
                      self.exp_current.setChecked(True)
                      self.exp_end_date.setEnabled(False)
                  else:
                      self.exp_current.setChecked(False)
                      self.exp_end_date.setDate(QDate.fromString(exp["end_date"], "yyyy-MM-dd"))
                      self.exp_end_date.setEnabled(True)
                  
                  self.exp_description.setPlainText(exp["description"])
              
              def update_experience_list(self):
                  self.exp_list.clear()
                  for exp in self.resume_data["experience"]:
                      item = QListWidgetItem(f"{exp['position']} - {exp['company']}")
                      self.exp_list.addItem(item)
              
              def clear_experience_form(self):
                  self.exp_company_edit.clear()
                  self.exp_position_edit.clear()
                  self.exp_start_date.setDate(QDate.currentDate())
                  self.exp_end_date.setDate(QDate.currentDate())
                  self.exp_current.setChecked(False)
                  self.exp_description.clear()
                  self.exp_end_date.setEnabled(True)
              
              def add_skill(self):
                  skill = f"{self.skill_edit.text()} ({self.skill_level_combo.currentText()})"
                  self.resume_data["skills"].append(skill)
                  self.update_skills_list()
                  self.skill_edit.clear()
              
              def remove_skill(self):
                  for item in self.skill_list.selectedItems():
                      index = self.skill_list.row(item)
                      self.resume_data["skills"].pop(index)
                      self.skill_list.takeItem(index)
              
              def update_skills_list(self):
                  self.skill_list.clear()
                  for skill in self.resume_data["skills"]:
                      self.skill_list.addItem(skill)
              
              def add_project(self):
                  self.collect_personal_info()
                  
                  proj = {
                      "name": self.proj_name_edit.text(),
                      "role": self.proj_role_edit.text(),
                      "start_date": self.proj_start_date.date().toString("yyyy-MM-dd"),
                      "end_date": "" if self.proj_current.isChecked() else self.proj_end_date.date().toString("yyyy-MM-dd"),
                      "current": self.proj_current.isChecked(),
                      "url": self.proj_url_edit.text(),
                      "description": self.proj_description.toPlainText()
                  }
                  
                  self.resume_data["projects"].append(proj)
                  self.update_project_list()
                  self.clear_project_form()
              
              def update_project(self):
                  if self.current_proj_index == -1:
                      return
                      
                  proj = {
                      "name": self.proj_name_edit.text(),
                      "role": self.proj_role_edit.text(),
                      "start_date": self.proj_start_date.date().toString("yyyy-MM-dd"),
                      "end_date": "" if self.proj_current.isChecked() else self.proj_end_date.date().toString("yyyy-MM-dd"),
                      "current": self.proj_current.isChecked(),
                      "url": self.proj_url_edit.text(),
                      "description": self.proj_description.toPlainText()
                  }
                  
                  self.resume_data["projects"][self.current_proj_index] = proj
                  self.update_project_list()
                  self.clear_project_form()
                  self.current_proj_index = -1
              
              def remove_project(self):
                  if self.current_proj_index == -1:
                      return
                      
                  self.resume_data["projects"].pop(self.current_proj_index)
                  self.update_project_list()
                  self.clear_project_form()
                  self.current_proj_index = -1
              
              def load_project(self, item):
                  index = self.proj_list.row(item)
                  self.current_proj_index = index
                  proj = self.resume_data["projects"][index]
                  
                  self.proj_name_edit.setText(proj["name"])
                  self.proj_role_edit.setText(proj["role"])
                  self.proj_start_date.setDate(QDate.fromString(proj["start_date"], "yyyy-MM-dd"))
                  
                  if proj["current"]:
                      self.proj_current.setChecked(True)
                      self.proj_end_date.setEnabled(False)
                  else:
                      self.proj_current.setChecked(False)
                      self.proj_end_date.setDate(QDate.fromString(proj["end_date"], "yyyy-MM-dd"))
                      self.proj_end_date.setEnabled(True)
                  
                  self.proj_url_edit.setText(proj["url"])
                  self.proj_description.setPlainText(proj["description"])
              
              def update_project_list(self):
                  self.proj_list.clear()
                  for proj in self.resume_data["projects"]:
                      item = QListWidgetItem(f"{proj['name']} ({proj['role']})")
                      self.proj_list.addItem(item)
              
              def clear_project_form(self):
                  self.proj_name_edit.clear()
                  self.proj_role_edit.clear()
                  self.proj_start_date.setDate(QDate.currentDate())
                  self.proj_end_date.setDate(QDate.currentDate())
                  self.proj_current.setChecked(False)
                  self.proj_url_edit.clear()
                  self.proj_description.clear()
                  self.proj_end_date.setEnabled(True)
              
              def add_certification(self):
                  self.collect_personal_info()
                  
                  cert = {
                      "name": self.cert_name_edit.text(),
                      "organization": self.cert_org_edit.text(),
                      "date": self.cert_date.date().toString("yyyy-MM-dd"),
                      "url": self.cert_url_edit.text()
                  }
                  
                  self.resume_data["certifications"].append(cert)
                  self.update_certification_list()
                  self.clear_certification_form()
              
              def update_certification(self):
                  if self.current_cert_index == -1:
                      return
                      
                  cert = {
                      "name": self.cert_name_edit.text(),
                      "organization": self.cert_org_edit.text(),
                      "date": self.cert_date.date().toString("yyyy-MM-dd"),
                      "url": self.cert_url_edit.text()
                  }
                  
                  self.resume_data["certifications"][self.current_cert_index] = cert
                  self.update_certification_list()
                  self.clear_certification_form()
                  self.current_cert_index = -1
              
              def remove_certification(self):
                  if self.current_cert_index == -1:
                      return
                      
                  self.resume_data["certifications"].pop(self.current_cert_index)
                  self.update_certification_list()
                  self.clear_certification_form()
                  self.current_cert_index = -1
              
              def load_certification(self, item):
                  index = self.cert_list.row(item)
                  self.current_cert_index = index
                  cert = self.resume_data["certifications"][index]
                  
                  self.cert_name_edit.setText(cert["name"])
                  self.cert_org_edit.setText(cert["organization"])
                  self.cert_date.setDate(QDate.fromString(cert["date"], "yyyy-MM-dd"))
                  self.cert_url_edit.setText(cert["url"])
              
              def update_certification_list(self):
                  self.cert_list.clear()
                  for cert in self.resume_data["certifications"]:
                      item = QListWidgetItem(f"{cert['name']} - {cert['organization']}")
                      self.cert_list.addItem(item)
              
              def clear_certification_form(self):
                  self.cert_name_edit.clear()
                  self.cert_org_edit.clear()
                  self.cert_date.setDate(QDate.currentDate())
                  self.cert_url_edit.clear()
              
              def add_language(self):
                  lang = f"{self.lang_edit.text()} ({self.lang_level_combo.currentText()})"
                  self.resume_data["languages"].append(lang)
                  self.update_languages_list()
                  self.lang_edit.clear()
              
              def remove_language(self):
                  for item in self.lang_list.selectedItems():
                      index = self.lang_list.row(item)
                      self.resume_data["languages"].pop(index)
                      self.lang_list.takeItem(index)
              
              def update_languages_list(self):
                  self.lang_list.clear()
                  for lang in self.resume_data["languages"]:
                      self.lang_list.addItem(lang)
              
              def preview_resume(self):
                  """生成简历预览"""
                  self.collect_personal_info()
                  self.collect_summary()
                  
                  preview_text = "=== 简历预览 ===nn"
                  preview_text += "🌟 个人信息:n"
                  preview_text += f"👤 姓名: {self.resume_data['personal_info']['name']}n"
                  preview_text += f"✉️ 邮箱: {self.resume_data['personal_info']['email']}n"
                  preview_text += f"📱 电话: {self.resume_data['personal_info']['phone']}n"
                  preview_text += f"🏠 地址: {self.resume_data['personal_info']['address']}n"
                  preview_text += f"🔗 LinkedIn: {self.resume_data['personal_info']['linkedin']}n"
                  preview_text += f"💻 GitHub: {self.resume_data['personal_info']['github']}n"
                  preview_text += f"🌐 个人网站: {self.resume_data['personal_info']['website']}nn"
                  
                  preview_text += "📝 职业概述:n"
                  preview_text += f"{self.resume_data['summary']}nn"
                  
                  preview_text += "🎓 教育经历:n"
                  for edu in self.resume_data["education"]:
                      preview_text += f"- 🎓 {edu['degree']} - {edu['school']} ({edu['field']})n"
                      preview_text += f"  📅 {edu['start_date']} 至 {'至今' if edu['current'] else edu['end_date']}n"
                      preview_text += f"  📊 GPA: {edu['gpa']}n"
                      preview_text += f"  📋 描述: {edu['description']}nn"
                  
                  preview_text += "💼 工作经历:n"
                  for exp in self.resume_data["experience"]:
                      preview_text += f"- 💼 {exp['position']} - {exp['company']}n"
                      preview_text += f"  📅 {exp['start_date']} 至 {'至今' if exp['current'] else exp['end_date']}n"
                      preview_text += f"  📋 描述: {exp['description']}nn"
                  
                  preview_text += "🛠️ 技能:n"
                  for skill in self.resume_data["skills"]:
                      preview_text += f"- {skill}n"
                  preview_text += "n"
                  
                  preview_text += "📂 项目经历:n"
                  for proj in self.resume_data["projects"]:
                      preview_text += f"- 📂 {proj['name']} ({proj['role']})n"
                      preview_text += f"  📅 {proj['start_date']} 至 {'进行中' if proj['current'] else proj['end_date']}n"
                      preview_text += f"  🔗 URL: {proj['url']}n"
                      preview_text += f"  📋 描述: {proj['description']}nn"
                  
                  preview_text += "📜 证书:n"
                  for cert in self.resume_data["certifications"]:
                      preview_text += f"- 📜 {cert['name']} - {cert['organization']} ({cert['date']})n"
                      preview_text += f"  🔗 URL: {cert['url']}nn"
                  
                  preview_text += "🌐 语言能力:n"
                  for lang in self.resume_data["languages"]:
                      preview_text += f"- {lang}n"
                  
                  self.preview_text.setPlainText(preview_text)
              
              def export_to_pdf(self):
                  self.collect_personal_info()
                  self.collect_summary()
                  
                  # 创建PDF
                  pdf = FPDF()
                  pdf.add_page()
                  pdf.set_auto_page_break(auto=True, margin=15)
                  
                  # 设置字体
                  pdf.set_font("Arial", 'B', 16)
                  
                  # 个人信息
                  pdf.cell(0, 10, self.resume_data["personal_info"]["name"], 0, 1, 'C')
                  pdf.set_font("Arial", '', 12)
                  
                  contact_info = []
                  if self.resume_data["personal_info"]["email"]:
                      contact_info.append(self.resume_data["personal_info"]["email"])
                  if self.resume_data["personal_info"]["phone"]:
                      contact_info.append(self.resume_data["personal_info"]["phone"])
                  if self.resume_data["personal_info"]["address"]:
                      contact_info.append(self.resume_data["personal_info"]["address"])
                  
                  pdf.cell(0, 10, " | ".join(contact_info), 0, 1, 'C')
                  
                  # 添加链接
                  links = []
                  if self.resume_data["personal_info"]["linkedin"]:
                      links.append(f"LinkedIn: {self.resume_data['personal_info']['linkedin']}")
                  if self.resume_data["personal_info"]["github"]:
                      links.append(f"GitHub: {self.resume_data['personal_info']['github']}")
                  if self.resume_data["personal_info"]["website"]:
                      links.append(f"Website: {self.resume_data['personal_info']['website']}")
                  
                  if links:
                      pdf.cell(0, 10, " | ".join(links), 0, 1, 'C')
                  
                  pdf.ln(10)
                  
                  # 职业概述
                  if self.resume_data["summary"]:
                      pdf.set_font("Arial", 'B', 14)
                      pdf.cell(0, 10, "职业概述", 0, 1, 'L')
                      pdf.set_font("Arial", '', 12)
                      pdf.multi_cell(0, 6, self.resume_data["summary"])
                      pdf.ln(5)
                  
                  # 教育经历
                  if self.resume_data["education"]:
                      pdf.set_font("Arial", 'B', 14)
                      pdf.cell(0, 10, "教育经历", 0, 1, 'L')
                      pdf.set_font("Arial", '', 12)
                      
                      for edu in self.resume_data["education"]:
                          pdf.set_font("Arial", 'B', 12)
                          pdf.cell(0, 6, f"{edu['degree']} - {edu['school']}", 0, 1, 'L')
                          pdf.set_font("Arial", '', 12)
                          
                          date_range = f"{edu['start_date']} - {'至今' if edu['current'] else edu['end_date']}"
                          if edu["gpa"]:
                              date_range += f" | GPA: {edu['gpa']}"
                          
                          pdf.cell(0, 6, f"{edu['field']} | {date_range}", 0, 1, 'L')
                          
                          if edu["description"]:
                              pdf.multi_cell(0, 6, edu["description"])
                          
                          pdf.ln(2)
                  
                  # 工作经历
                  if self.resume_data["experience"]:
                      pdf.set_font("Arial", 'B', 14)
                      pdf.cell(0, 10, "工作经历", 0, 1, 'L')
                      pdf.set_font("Arial", '', 12)
                      
                      for exp in self.resume_data["experience"]:
                          pdf.set_font("Arial", 'B', 12)
                          pdf.cell(0, 6, f"{exp['position']} - {exp['company']}", 0, 1, 'L')
                          pdf.set_font("Arial", '', 12)
                          
                          pdf.cell(0, 6, f"{exp['start_date']} - {'至今' if exp['current'] else exp['end_date']}", 0, 1, 'L')
                          
                          if exp["description"]:
                              pdf.multi_cell(0, 6, exp["description"])
                          
                          pdf.ln(2)
                  
                  # 技能
                  if self.resume_data["skills"]:
                      pdf.set_font("Arial", 'B', 14)
                      pdf.cell(0, 10, "技能", 0, 1, 'L')
                      pdf.set_font("Arial", '', 12)
                      
                      skills = ", ".join(self.resume_data["skills"])
                      pdf.multi_cell(0, 6, skills)
                      pdf.ln(5)
                  
                  # 项目经历
                  if self.resume_data["projects"]:
                      pdf.set_font("Arial", 'B', 14)
                      pdf.cell(0, 10, "项目经历", 0, 1, 'L')
                      pdf.set_font("Arial", '', 12)
                      
                      for proj in self.resume_data["projects"]:
                          pdf.set_font("Arial", 'B', 12)
                          pdf.cell(0, 6, f"{proj['name']} ({proj['role']})", 0, 1, 'L')
                          pdf.set_font("Arial", '', 12)
                          
                          date_range = f"{proj['start_date']} - {'进行中' if proj['current'] else proj['end_date']}"
                          if proj["url"]:
                              date_range += f" | URL: {proj['url']}"
                          
                          pdf.cell(0, 6, date_range, 0, 1, 'L')
                          
                          if proj["description"]:
                              pdf.multi_cell(0, 6, proj["description"])
                          
                          pdf.ln(2)
                  
                  # 证书
                  if self.resume_data["certifications"]:
                      pdf.set_font("Arial", 'B', 14)
                      pdf.cell(0, 10, "证书", 0, 1, 'L')
                      pdf.set_font("Arial", '', 12)
                      
                      for cert in self.resume_data["certifications"]:
                          cert_line = f"{cert['name']} - {cert['organization']} ({cert['date']})"
                          if cert["url"]:
                              cert_line += f" | URL: {cert['url']}"
                          
                          pdf.cell(0, 6, cert_line, 0, 1, 'L')
                          pdf.ln(2)
                  
                  # 语言能力
                  if self.resume_data["languages"]:
                      pdf.set_font("Arial", 'B', 14)
                      pdf.cell(0, 10, "语言能力", 0, 1, 'L')
                      pdf.set_font("Arial", '', 12)
                      
                      langs = ", ".join(self.resume_data["languages"])
                      pdf.multi_cell(0, 6, langs)
                  
                  # 保存PDF
                  file_path, _ = QFileDialog.getSaveFileName(self, "保存PDF", "我的简历.pdf", "PDF文件 (*.pdf)")
                  if file_path:
                      pdf.output(file_path)
                      QMessageBox.information(self, "成功", "简历已成功导出为PDF!")
              
              def save_resume_data(self):
                  self.collect_personal_info()
                  self.collect_summary()
                  
                  file_path, _ = QFileDialog.getSaveFileName(self, "保存简历数据", "resume_data.json", "JSON文件 (*.json)")
                  if file_path:
                      with open(file_path, 'w', encoding='utf-8') as f:
                          json.dump(self.resume_data, f, ensure_ascii=False, indent=4)
                      QMessageBox.information(self, "成功", "简历数据已保存!")
              
              def load_resume_data(self):
                  file_path, _ = QFileDialog.getOpenFileName(self, "加载简历数据", "", "JSON文件 (*.json)")
                  if file_path:
                      try:
                          with open(file_path, 'r', encoding='utf-8') as f:
                              self.resume_data = json.load(f)
                          
                          # 更新UI
                          self.update_ui_from_data()
                          QMessageBox.information(self, "成功", "简历数据已加载!")
                      except Exception as e:
                          QMessageBox.critical(self, "错误", f"加载简历数据失败: {str(e)}")
              
              def update_ui_from_data(self):
                  # 个人信息
                  personal_info = self.resume_data["personal_info"]
                  self.name_edit.setText(personal_info.get("name", ""))
                  self.email_edit.setText(personal_info.get("email", ""))
                  self.phone_edit.setText(personal_info.get("phone", ""))
                  self.address_edit.setText(personal_info.get("address", ""))
                  self.linkedin_edit.setText(personal_info.get("linkedin", ""))
                  self.github_edit.setText(personal_info.get("github", ""))
                  self.website_edit.setText(personal_info.get("website", ""))
                  
                  # 职业概述
                  self.summary_edit.setPlainText(self.resume_data.get("summary", ""))
                  
                  # 教育经历
                  self.update_education_list()
                  
                  # 工作经历
                  self.update_experience_list()
                  
                  # 技能
                  self.update_skills_list()
                  
                  # 项目经历
                  self.update_project_list()
                  
                  # 证书
                  self.update_certification_list()
                  
                  # 语言能力
                  self.update_languages_list()
          
          if __name__ == "__main__":
              app = QApplication(sys.argv)
              
              # 设置应用程序样式和字体
              app.setStyle("Fusion")
              
              # 设置调色板
              palette = QPalette()
              palette.setColor(QPalette.Window, QColor(240, 242, 245))
              palette.setColor(QPalette.WindowText, QColor(0, 0, 0))
              palette.setColor(QPalette.Base, QColor(255, 255, 255))
              palette.setColor(QPalette.AlternateBase, QColor(240, 240, 240))
              palette.setColor(QPalette.ToolTipBase, QColor(255, 255, 255))
              palette.setColor(QPalette.ToolTipText, QColor(0, 0, 0))
              palette.setColor(QPalette.Text, QColor(0, 0, 0))
              palette.setColor(QPalette.Button, QColor(240, 240, 240))
              palette.setColor(QPalette.ButtonText, QColor(0, 0, 0))
              palette.setColor(QPalette.BrightText, QColor(255, 0, 0))
              palette.setColor(QPalette.Highlight, QColor(76, 175, 80))
              palette.setColor(QPalette.HighlightedText, QColor(255, 255, 255))
              app.setPalette(palette)
              
              # 创建并显示主窗口
              window = ResumeGenerator()
              window.show()
              
              sys.exit(app.exec_())
          

          本工具通过PyQt5实现了:

          • 高效管理:比传统文档编辑效率提升300%
          • 专业输出:符合HR系统的解析标准
          • 灵活定制:模块化设计易于扩展

          未来可增加:

          • LaTeX导出支持
          • 在线模板市场
          • AI辅助内容生成
          • 多语言国际化

          Q&A环节

          Q:如何添加自定义模板?

          A:在templates目录下新建JSON文件,按照现有模板格式编写样式规则。

          Q:程序无法显示中文怎么办?

          A:确保系统已安装中文字体,并在PDF生成时指定中文字体路径。

          Q:能否导出为Word格式?

          A:当前版本仅支持PDF,可通过python-docx库自行扩展。

          相关技术栈推荐

          • 高级功能:PyQtGraph数据可视化
          • 云存储:集成Dropbox API
          • 自动化:结合Selenium实现自动投递

          求职小贴士

          使用本工具生成简历后,建议:

          • 根据不同岗位调整关键词
          • 保持一页纸原则
          • 量化工作成果
          • 定期更新内容

          到此这篇关于Python+PyQt5实现简历自动生成工具的文章就介绍到这了,更多相关Python自动生成简历内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

          您可能感兴趣的文章:

          • python简单实现刷新智联简历
          • 使用C# CefSharp Python采集某网站简历并且自动发送邀请短信的方法
          • python+selenium实现简历自动刷新的示例代码
          • Python实现提取PDF简历信息并存入Excel
          • Python Word文件自动化实战之简历筛选
          • 利用Python实现自动生成数据日报
          • Python办公自动化之数据可视化与报表生成
          • python使用MkDocs自动生成文档的操作方法

          站内搜索