import sysimport jsonfrom datetime import datetimefrom PyQt6.QtWidgets import ( QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QTextEdit, QFileDialog, QMessageBox, QProgressBar, QGroupBox, QPlainTextEdit, QTabWidget, QLineEdit, QGridLayout, QLabel, QCheckBox)from PyQt6.QtCore import Qtfrom PyQt6.QtGui import QFontclass ResumeGeneratorUI(QMainWindow): """简历生成器主窗口""" def __init__(self): super().__init__() self.template_path = './模板/模板1.docx' self.initUI() self.load_config() def initUI(self): self.setWindowTitle('AI智能简历生成器') self.setGeometry(100, 100, 1000, 750) # 设置应用样式 self.setStyleSheet(""" QMainWindow { background-color: #f5f5f5; } QGroupBox { font-weight: bold; border: 2px solid #d0d0d0; border-radius: 6px; margin-top: 12px; padding-top: 12px; background-color: white; } QGroupBox::title { subcontrol-origin: margin; left: 12px; padding: 0 8px 0 8px; color: #2c3e50; } QPushButton { background-color: #3498db; color: white; border: none; padding: 8px 16px; border-radius: 4px; font-size: 13px; font-weight: bold; } QPushButton:hover { background-color: #2980b9; } QPushButton:pressed { background-color: #21618c; } QPushButton:disabled { background-color: #bdc3c7; color: #7f8c8d; } QPushButton#btn_generate { background-color: #27ae60; font-size: 15px; padding: 10px 24px; } QPushButton#btn_generate:hover { background-color: #229954; } QPushButton#btn_generate:disabled { background-color: #bdc3c7; } QPushButton#btn_browse { background-color: #95a5a6; } QPushButton#btn_browse:hover { background-color: #7f8c8d; } QLineEdit, QTextEdit, QPlainTextEdit { border: 1px solid #d0d0d0; border-radius: 4px; padding: 6px; font-family: "Microsoft YaHei"; background-color: white; } QLineEdit:focus, QTextEdit:focus, QPlainTextEdit:focus { border: 1px solid #3498db; } QProgressBar { border: 1px solid #d0d0d0; border-radius: 4px; text-align: center; background-color: white; } QProgressBar::chunk { background-color: #27ae60; border-radius: 4px; } QTabWidget::pane { border: 1px solid #d0d0d0; border-radius: 4px; background-color: white; } QTabBar::tab { background-color: #ecf0f1; padding: 6px 16px; margin-right: 2px; border-top-left-radius: 4px; border-top-right-radius: 4px; } QTabBar::tab:selected { background-color: white; border-bottom: 2px solid #3498db; } QTabBar::tab:hover { background-color: #d5dbdb; } QLabel { color: #2c3e50; } """) # 中心部件 central_widget = QWidget() self.setCentralWidget(central_widget) main_layout = QVBoxLayout(central_widget) main_layout.setSpacing(10) # 标题区域 title_label = QLabel('🎯 AI智能简历生成器') title_label.setAlignment(Qt.AlignmentFlag.AlignCenter) title_font = QFont('Microsoft YaHei', 20, QFont.Weight.Bold) title_label.setFont(title_font) title_label.setStyleSheet('color: #2c3e50; padding: 8px;') main_layout.addWidget(title_label) # 选项卡 tabs = QTabWidget() main_layout.addWidget(tabs) # 第一页:输入内容 input_tab = QWidget() tabs.addTab(input_tab, '📝 简历内容') input_layout = QVBoxLayout(input_tab) input_layout.setSpacing(10) # 配置区域 - 使用网格布局 config_group = QGroupBox('⚙️ 配置设置') config_layout = QGridLayout() config_layout.setSpacing(10) # 模板选择行 config_layout.addWidget(QLabel('📄 简历模板:'), 0, 0) template_widget = QWidget() template_layout = QHBoxLayout(template_widget) template_layout.setContentsMargins(0, 0, 0, 0) self.template_path_edit = QLineEdit() self.template_path_edit.setPlaceholderText('请选择简历模板文件...') self.template_path_edit.setReadOnly(True) template_layout.addWidget(self.template_path_edit) self.browse_btn = QPushButton('浏览...') self.browse_btn.setObjectName('btn_browse') self.browse_btn.clicked.connect(self.browse_template) template_layout.addWidget(self.browse_btn) config_layout.addWidget(template_widget, 0, 1) # API Key行 config_layout.addWidget(QLabel('🔑 API Key:'), 1, 0) self.api_key_edit = QLineEdit() self.api_key_edit.setPlaceholderText('请输入您的API Key (格式: key:secret)') self.api_key_edit.setEchoMode(QLineEdit.EchoMode.Password) config_layout.addWidget(self.api_key_edit, 1, 1) # 显示API Key复选框 self.show_api_key = QCheckBox('显示API Key') self.show_api_key.stateChanged.connect(self.toggle_api_key_visibility) config_layout.addWidget(self.show_api_key, 2, 1, alignment=Qt.AlignmentFlag.AlignRight) # 自定义要求行 config_layout.addWidget(QLabel('📝 自定义要求:'), 3, 0) self.custom_input = QLineEdit() self.custom_input.setPlaceholderText('如:突出项目经历,强调专业技能等') config_layout.addWidget(self.custom_input, 3, 1) config_group.setLayout(config_layout) input_layout.addWidget(config_group) # 简历内容编辑区 content_group = QGroupBox('📄 简历内容(请在此粘贴或加载简历文本)') content_layout = QVBoxLayout() self.content_edit = QPlainTextEdit() self.content_edit.setPlaceholderText( '请将您的简历文本粘贴到这里...\n\n支持的格式:\n- 教育背景\n- 工作/实习经历\n- 项目经历\n- 技能证书\n- 荣誉奖项\n- 自我评价等' ) content_layout.addWidget(self.content_edit) # 按钮区域 btn_layout = QHBoxLayout() btn_layout.addStretch() self.load_btn = QPushButton('📂 加载简历文件') self.load_btn.clicked.connect(self.load_file) btn_layout.addWidget(self.load_btn) self.save_btn = QPushButton('💾 保存到文件') self.save_btn.clicked.connect(self.save_content) btn_layout.addWidget(self.save_btn) btn_layout.addStretch() content_layout.addLayout(btn_layout) content_group.setLayout(content_layout) input_layout.addWidget(content_group) # 第二页:日志输出 log_tab = QWidget() tabs.addTab(log_tab, '📋 生成日志') log_layout = QVBoxLayout(log_tab) self.log_output = QTextEdit() self.log_output.setReadOnly(True) self.log_output.setStyleSheet('font-family: "Consolas", "Microsoft YaHei"; font-size: 11px; background-color: #fafafa;') log_layout.addWidget(self.log_output) # 底部控制区域 bottom_widget = QWidget() bottom_layout = QVBoxLayout(bottom_widget) bottom_layout.setSpacing(10) # 进度条 self.progress_bar = QProgressBar() self.progress_bar.setVisible(False) self.progress_bar.setMinimumHeight(25) bottom_layout.addWidget(self.progress_bar) # 操作按钮 action_layout = QHBoxLayout() action_layout.addStretch() self.generate_btn = QPushButton('🚀 生成简历') self.generate_btn.setObjectName('btn_generate') self.generate_btn.clicked.connect(self.generate_resume) self.generate_btn.setMinimumWidth(180) self.generate_btn.setMinimumHeight(40) action_layout.addWidget(self.generate_btn) self.clear_log_btn = QPushButton('🗑️ 清空日志') self.clear_log_btn.clicked.connect(self.clear_log) action_layout.addWidget(self.clear_log_btn) action_layout.addStretch() bottom_layout.addLayout(action_layout) main_layout.addWidget(bottom_widget) # 初始化日志 self.log('🌟 欢迎使用AI智能简历生成器!') self.log('📌 使用步骤:') self.log(' 1. 选择简历模板文件(点击"浏览..."按钮)') self.log(' 2. 输入API Key') self.log(' 3. 粘贴或加载简历文本内容') self.log(' 4. 点击"生成简历"按钮') self.log(' 5. 等待AI处理完成,查看生成结果') def browse_template(self): """浏览选择模板文件""" file_path, _ = QFileDialog.getOpenFileName( self, '选择简历模板文件', './模板/', 'Word文档 (*.docx);;所有文件 (*.*)' ) if file_path: self.template_path_edit.setText(file_path) self.template_path = file_path self.log(f'✅ 已选择模板: {file_path}') def toggle_api_key_visibility(self, state): """切换API Key可见性""" if state == Qt.CheckState.Checked: self.api_key_edit.setEchoMode(QLineEdit.EchoMode.Normal) else: self.api_key_edit.setEchoMode(QLineEdit.EchoMode.Password) def load_config(self): """加载配置文件""" try: with open('./配置.json', 'r', encoding='utf-8') as f: config = json.load(f) # 加载模板路径 template = config.get('模板路径', '') if template: self.template_path_edit.setText(template) self.template_path = template # 加载API Key api_key = config.get('api_key', '') if api_key: self.api_key_edit.setText(api_key) # 加载自定义要求 custom = config.get('自定义内容', '') self.custom_input.setText(custom) # 加载简历内容 try: with open('./简历内容.txt', 'r', encoding='utf-8') as f: content = f.read() self.content_edit.setPlainText(content) except: pass self.log('✅ 配置加载成功') except Exception as e: self.log(f'⚠️ 加载配置失败: {str(e)}') def save_config(self): """保存配置""" try: config = { '模板路径': self.template_path, 'api_key': self.api_key_edit.text(), '自定义内容': self.custom_input.text() } with open('./配置.json', 'w', encoding='utf-8') as f: json.dump(config, f, ensure_ascii=False, indent=2) self.log('✅ 配置已保存') except Exception as e: self.log(f'⚠️ 保存配置失败: {str(e)}') def load_file(self): """加载简历文件""" file_path, _ = QFileDialog.getOpenFileName( self, '选择简历文件', './', '文本文件 (*.txt);;所有文件 (*.*)' ) if file_path: try: with open(file_path, 'r', encoding='utf-8') as f: content = f.read() self.content_edit.setPlainText(content) self.log(f'✅ 已加载文件: {file_path}') except Exception as e: QMessageBox.warning(self, '错误', f'加载文件失败:{str(e)}') self.log(f'❌ 加载文件失败: {str(e)}') def save_content(self): """保存简历内容""" file_path, _ = QFileDialog.getSaveFileName( self, '保存简历内容', './简历内容.txt', '文本文件 (*.txt)' ) if file_path: try: with open(file_path, 'w', encoding='utf-8') as f: f.write(self.content_edit.toPlainText()) self.log(f'✅ 内容已保存到: {file_path}') except Exception as e: QMessageBox.warning(self, '错误', f'保存失败:{str(e)}') self.log(f'❌ 保存失败: {str(e)}') def log(self, message): """添加日志""" timestamp = datetime.now().strftime('%H:%M:%S') self.log_output.append(f'[{timestamp}] {message}') # 自动滚动到底部 scrollbar = self.log_output.verticalScrollBar() scrollbar.setValue(scrollbar.maximum()) def clear_log(self): """清空日志""" self.log_output.clear() self.log('🗑️ 日志已清空') def generate_resume(self): """生成简历(占位方法,实际功能由外部线程实现)""" # 检查模板路径 if not self.template_path or not self.template_path.endswith('.docx'): QMessageBox.warning(self, '提示', '请先选择有效的简历模板文件!') self.log('❌ 请先选择简历模板文件') return # 检查API Key api_key = self.api_key_edit.text().strip() if not api_key: QMessageBox.warning(self, '提示', '请输入API Key!') self.log('❌ 请输入API Key') return # 检查简历内容 content = self.content_edit.toPlainText().strip() if not content: QMessageBox.warning(self, '提示', '请先输入或加载简历内容!') self.log('❌ 请先输入简历内容') return # 保存配置 self.save_config() # 保存简历内容到文件 try: with open('./简历内容.txt', 'w', encoding='utf-8') as f: f.write(content) except: pass # 禁用生成按钮 self.generate_btn.setEnabled(False) self.progress_bar.setVisible(True) self.progress_bar.setValue(0) self.log('🚀 开始生成简历...') # 此处调用外部生成逻辑 # 实际使用时,这里会启动一个QThread来执行生成任务 self.log('⏳ 正在处理,请稍候...') # 模拟进度(仅用于演示界面效果) import time for i in range(1, 101, 10): self.progress_bar.setValue(i) self.log(f'📊 进度: {i}%') time.sleep(0.1) # 模拟完成 self.progress_bar.setValue(100) self.generate_btn.setEnabled(True) self.progress_bar.setVisible(False) self.log('✅ 简历生成完成!(演示模式)') QMessageBox.information(self, '提示', '简历生成完成!(演示模式)\n\n实际功能需要集成AI生成逻辑。')def main(): app = QApplication(sys.argv) app.setStyle('Fusion') window = ResumeGeneratorUI() window.show() sys.exit(app.exec())if __name__ == '__main__': main()