| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- import sys
- import json
- from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QHBoxLayout,
- QVBoxLayout, QListWidget, QListWidgetItem, QCheckBox,
- QPushButton, QLineEdit, QTextEdit, QGroupBox,
- QSplitter, QLabel, QMessageBox, QComboBox, QShortcut)
- from PyQt5.QtCore import Qt
- from PyQt5.QtGui import QKeySequence
- class MainWindow(QMainWindow):
- def __init__(self):
- super().__init__()
- self.setWindowTitle("三栏布局 - 用户独立话术管理 (快捷键F1-F5)")
- self.setGeometry(100, 100, 1300, 750)
-
- # 数据存储:用户话术字典 {用户名: [话术列表]}
- self.user_scripts = {}
- # 当前选中的用户
- self.current_user = None
-
- # 中央部件
- central_widget = QWidget()
- self.setCentralWidget(central_widget)
-
- # 主布局 - 水平分割器
- main_splitter = QSplitter(Qt.Horizontal)
- central_layout = QHBoxLayout(central_widget)
- central_layout.addWidget(main_splitter)
- central_layout.setContentsMargins(10, 10, 10, 10)
-
- # ---------- 左侧:日志显示 ----------
- left_widget = QWidget()
- left_layout = QVBoxLayout(left_widget)
- left_layout.setContentsMargins(5, 5, 5, 5)
-
- log_label = QLabel("📋 运行日志")
- log_label.setStyleSheet("font-weight: bold; font-size: 14px;")
- left_layout.addWidget(log_label)
-
- self.log_text = QTextEdit()
- self.log_text.setReadOnly(True)
- self.log_text.setPlaceholderText("日志信息将显示在这里...")
- self.log_text.append("[系统] 程序启动")
- self.log_text.append("[系统] 界面初始化完成")
- self.log_text.append("[系统] 快捷键: F1-F5 快速切换用户")
- left_layout.addWidget(self.log_text)
-
- log_btn_layout = QHBoxLayout()
- clear_log_btn = QPushButton("清空日志")
- clear_log_btn.clicked.connect(self.clear_log)
- log_btn_layout.addStretch()
- log_btn_layout.addWidget(clear_log_btn)
- left_layout.addLayout(log_btn_layout)
-
- # ---------- 中间:在线用户列表 ----------
- middle_widget = QWidget()
- middle_layout = QVBoxLayout(middle_widget)
- middle_layout.setContentsMargins(5, 5, 5, 5)
-
- user_label = QLabel("👥 在线用户列表")
- user_label.setStyleSheet("font-weight: bold; font-size: 14px;")
- middle_layout.addWidget(user_label)
-
- select_btn_layout = QHBoxLayout()
- self.select_all_btn = QPushButton("✅ 全选")
- self.deselect_all_btn = QPushButton("❌ 取消全选")
- self.select_all_btn.clicked.connect(self.select_all_users)
- self.deselect_all_btn.clicked.connect(self.deselect_all_users)
- select_btn_layout.addWidget(self.select_all_btn)
- select_btn_layout.addWidget(self.deselect_all_btn)
- select_btn_layout.addStretch()
- middle_layout.addLayout(select_btn_layout)
-
- self.user_list_widget = QListWidget()
- self.user_list_widget.setSelectionMode(QListWidget.NoSelection)
- # 添加示例用户
- sample_users = ["用户A", "用户B", "用户C", "用户D", "用户E"]
- for user in sample_users:
- self.add_user_item(user)
- # 初始化用户话术数据
- self.user_scripts[user] = [f"话术1: 您好{user},请问有什么可以帮您?",
- f"话术2: {user},感谢您的反馈,我们会尽快处理。",
- f"话术3: {user},请您稍等,我为您转接专员。"]
- middle_layout.addWidget(self.user_list_widget)
-
- user_count_label = QLabel(f"当前在线人数: {self.user_list_widget.count()}")
- user_count_label.setStyleSheet("color: gray;")
- middle_layout.addWidget(user_count_label)
-
- # ---------- 右侧:用户独立话术列表 ----------
- right_widget = QWidget()
- right_layout = QVBoxLayout(right_widget)
- right_layout.setContentsMargins(5, 5, 5, 5)
-
- # 顶部:用户选择下拉框
- user_select_layout = QHBoxLayout()
- user_select_layout.addWidget(QLabel("选择用户 (快捷键F1-F5):"))
- self.user_combo = QComboBox()
- self.user_combo.addItems(sample_users)
- self.user_combo.currentTextChanged.connect(self.on_user_changed)
- user_select_layout.addWidget(self.user_combo)
- user_select_layout.addStretch()
- right_layout.addLayout(user_select_layout)
-
- # 话术列表标题
- script_label = QLabel("📝 话术列表 (当前用户)")
- script_label.setStyleSheet("font-weight: bold; font-size: 14px;")
- right_layout.addWidget(script_label)
-
- # 话术列表显示
- self.script_list_widget = QListWidget()
- right_layout.addWidget(self.script_list_widget)
-
- # 话术编辑区域
- script_edit_layout = QVBoxLayout()
-
- # 添加话术
- add_layout = QHBoxLayout()
- self.script_input = QLineEdit()
- self.script_input.setPlaceholderText("输入新话术内容...")
- add_btn = QPushButton("➕ 添加")
- add_btn.clicked.connect(self.add_script)
- add_layout.addWidget(self.script_input)
- add_layout.addWidget(add_btn)
- script_edit_layout.addLayout(add_layout)
-
- # 删除和修改按钮
- modify_layout = QHBoxLayout()
- delete_btn = QPushButton("🗑️ 删除选中")
- delete_btn.clicked.connect(self.delete_script)
- modify_btn = QPushButton("✏️ 修改选中")
- modify_btn.clicked.connect(self.modify_script)
- modify_layout.addWidget(delete_btn)
- modify_layout.addWidget(modify_btn)
- script_edit_layout.addLayout(modify_layout)
-
- # 保存按钮
- save_layout = QHBoxLayout()
- save_layout.addStretch()
- self.save_scripts_btn = QPushButton("💾 保存话术配置")
- self.save_scripts_btn.setStyleSheet("background-color: #2196F3; color: white; font-weight: bold; padding: 8px 20px; border-radius: 5px;")
- self.save_scripts_btn.clicked.connect(self.save_user_scripts)
- save_layout.addWidget(self.save_scripts_btn)
- script_edit_layout.addLayout(save_layout)
-
- right_layout.addLayout(script_edit_layout)
-
- # 发送任务按钮
- send_layout = QHBoxLayout()
- send_layout.addStretch()
- self.send_task_btn = QPushButton("🚀 发送任务")
- self.send_task_btn.setStyleSheet("background-color: #4CAF50; color: white; font-weight: bold; padding: 8px 20px; border-radius: 5px;")
- self.send_task_btn.clicked.connect(self.send_task)
- send_layout.addWidget(self.send_task_btn)
- right_layout.addLayout(send_layout)
-
- # ---------- 将三个部件加入分割器 ----------
- main_splitter.addWidget(left_widget)
- main_splitter.addWidget(middle_widget)
- main_splitter.addWidget(right_widget)
- main_splitter.setSizes([300, 450, 450])
-
- # 初始化显示第一个用户的话术
- if sample_users:
- self.current_user = sample_users[0]
- self.load_user_scripts(self.current_user)
-
- # ---------- 设置快捷键 F1-F5 ----------
- self.setup_shortcuts()
-
- # 窗口样式
- self.setStyleSheet("""
- QGroupBox {
- font-weight: bold;
- border: 1px solid #ccc;
- border-radius: 5px;
- margin-top: 10px;
- }
- QGroupBox::title {
- subcontrol-origin: margin;
- left: 10px;
- padding: 0 5px 0 5px;
- }
- QListWidget::item {
- padding: 5px;
- }
- QTextEdit {
- background-color: #f8f8f8;
- font-family: Consolas, monospace;
- }
- QComboBox {
- padding: 5px;
- min-width: 150px;
- }
- """)
-
- # ---------- 快捷键设置 ----------
- def setup_shortcuts(self):
- """设置F1-F5快捷键切换用户"""
- # F1 选择第一个用户,F2 第二个,以此类推
- shortcuts = [
- (Qt.Key_F1, 0),
- (Qt.Key_F2, 1),
- (Qt.Key_F3, 2),
- (Qt.Key_F4, 3),
- (Qt.Key_F5, 4),
- ]
-
- for key, index in shortcuts:
- shortcut = QShortcut(QKeySequence(key), self)
- # 使用lambda捕获index,并绑定到切换函数
- shortcut.activated.connect(lambda idx=index: self.switch_to_user_by_index(idx))
-
- def switch_to_user_by_index(self, index):
- """根据索引切换到对应用户"""
- if index < self.user_combo.count():
- user = self.user_combo.itemText(index)
- self.user_combo.setCurrentText(user)
- self.log_text.append(f"[快捷键] 切换到用户: {user}")
- else:
- self.log_text.append(f"[快捷键] 用户索引 {index} 不存在")
-
- # ---------- 用户管理 ----------
- def add_user_item(self, username):
- """添加一个带复选框的用户项"""
- item = QListWidgetItem()
- checkbox = QCheckBox(username)
- self.user_list_widget.addItem(item)
- self.user_list_widget.setItemWidget(item, checkbox)
- checkbox.stateChanged.connect(self.on_user_check_changed)
-
- def get_user_checkboxes(self):
- """获取所有用户复选框"""
- checkboxes = []
- for i in range(self.user_list_widget.count()):
- item = self.user_list_widget.item(i)
- widget = self.user_list_widget.itemWidget(item)
- if isinstance(widget, QCheckBox):
- checkboxes.append(widget)
- return checkboxes
-
- def get_selected_users(self):
- """获取所有选中的用户"""
- selected = []
- for cb in self.get_user_checkboxes():
- if cb.isChecked():
- selected.append(cb.text())
- return selected
-
- def select_all_users(self):
- for cb in self.get_user_checkboxes():
- cb.setChecked(True)
- self.log_text.append("[操作] 已全选所有用户")
-
- def deselect_all_users(self):
- for cb in self.get_user_checkboxes():
- cb.setChecked(False)
- self.log_text.append("[操作] 已取消全选所有用户")
-
- def on_user_check_changed(self):
- """复选框状态改变时更新下拉框列表"""
- # 获取当前所有用户
- current_users = []
- for i in range(self.user_list_widget.count()):
- item = self.user_list_widget.item(i)
- widget = self.user_list_widget.itemWidget(item)
- if isinstance(widget, QCheckBox):
- current_users.append(widget.text())
-
- # 更新下拉框
- current_selection = self.user_combo.currentText()
- self.user_combo.clear()
- self.user_combo.addItems(current_users)
-
- # 如果之前的用户还在列表中,恢复选择
- if current_selection in current_users:
- self.user_combo.setCurrentText(current_selection)
- elif current_users:
- self.user_combo.setCurrentIndex(0)
-
- # ---------- 话术管理 (用户独立) ----------
- def load_user_scripts(self, username):
- """加载指定用户的话术列表"""
- if username in self.user_scripts:
- self.script_list_widget.clear()
- for script in self.user_scripts[username]:
- self.script_list_widget.addItem(script)
- self.current_user = username
- self.log_text.append(f"[系统] 加载用户 '{username}' 的话术列表")
-
- def on_user_changed(self, username):
- """下拉框切换用户"""
- if username and username != self.current_user:
- # 如果当前用户有修改但未保存,先保存
- if self.current_user and self.current_user in self.user_scripts:
- # 自动保存当前用户的话术
- self.save_current_user_scripts()
-
- self.load_user_scripts(username)
-
- def save_current_user_scripts(self):
- """保存当前用户的话术到内存"""
- if self.current_user and self.current_user in self.user_scripts:
- scripts = []
- for i in range(self.script_list_widget.count()):
- scripts.append(self.script_list_widget.item(i).text())
- self.user_scripts[self.current_user] = scripts
- self.log_text.append(f"[系统] 自动保存用户 '{self.current_user}' 的话术配置")
-
- def save_user_scripts(self):
- """手动保存当前用户的话术(并持久化)"""
- if not self.current_user:
- QMessageBox.warning(self, "提示", "请先选择一个用户!")
- return
-
- # 保存到内存
- self.save_current_user_scripts()
-
- # 持久化保存到文件
- try:
- with open("user_scripts_backup.json", "w", encoding="utf-8") as f:
- json.dump(self.user_scripts, f, ensure_ascii=False, indent=2)
- self.log_text.append(f"[系统] 话术配置已保存到文件 user_scripts_backup.json")
- QMessageBox.information(self, "保存成功", f"用户 '{self.current_user}' 的话术配置已保存!")
- except Exception as e:
- QMessageBox.critical(self, "保存失败", f"保存到文件时出错: {str(e)}")
-
- def add_script(self):
- """添加话术到当前用户"""
- text = self.script_input.text().strip()
- if text:
- self.script_list_widget.addItem(text)
- self.script_input.clear()
- # 自动保存
- self.save_current_user_scripts()
- self.log_text.append(f"[操作] 为用户 '{self.current_user}' 添加话术: {text}")
- else:
- QMessageBox.information(self, "提示", "话术内容不能为空!")
-
- def delete_script(self):
- """删除当前用户选中的话术"""
- current_row = self.script_list_widget.currentRow()
- if current_row >= 0:
- item_text = self.script_list_widget.item(current_row).text()
- self.script_list_widget.takeItem(current_row)
- # 自动保存
- self.save_current_user_scripts()
- self.log_text.append(f"[操作] 删除用户 '{self.current_user}' 的话术: {item_text}")
- else:
- QMessageBox.information(self, "提示", "请先选中一条话术!")
-
- def modify_script(self):
- """修改当前用户选中的话术"""
- current_row = self.script_list_widget.currentRow()
- if current_row >= 0:
- old_text = self.script_list_widget.item(current_row).text()
- new_text, ok = QMessageBox.getText(self, "修改话术", "请输入新的话术内容:",
- text=old_text)
- if ok and new_text.strip():
- self.script_list_widget.item(current_row).setText(new_text.strip())
- # 自动保存
- self.save_current_user_scripts()
- self.log_text.append(f"[操作] 修改用户 '{self.current_user}' 的话术: {old_text} -> {new_text.strip()}")
- elif ok and not new_text.strip():
- QMessageBox.information(self, "提示", "话术内容不能为空!")
- else:
- QMessageBox.information(self, "提示", "请先选中一条话术!")
-
- def clear_log(self):
- self.log_text.clear()
- self.log_text.append("[系统] 日志已清空")
- self.log_text.append("[系统] 快捷键: F1-F5 快速切换用户")
-
- # ---------- 发送任务 ----------
- def send_task(self):
- """发送任务到选中的用户"""
- selected_users = self.get_selected_users()
-
- if not selected_users:
- QMessageBox.warning(self, "提示", "请至少选择一个用户!")
- return
-
- # 获取每个用户选中的话术 (这里演示:取每个用户的第一条话术)
- task_details = []
- for user in selected_users:
- if user in self.user_scripts and self.user_scripts[user]:
- script = self.user_scripts[user][0] # 取第一条
- task_details.append(f"{user}: {script}")
- else:
- task_details.append(f"{user}: (无话术)")
-
- # 记录日志
- self.log_text.append(f"[任务] 发送给 {len(selected_users)} 个用户:")
- for detail in task_details:
- self.log_text.append(f" - {detail}")
- self.log_text.append("[任务] 发送完成 (功能待实现)")
-
- # 显示详情
- msg = "\n".join(task_details)
- QMessageBox.information(self, "发送任务",
- f"已发送任务给 {len(selected_users)} 个用户:\n\n{msg}")
-
- # ---------- 窗口关闭时保存 ----------
- def closeEvent(self, event):
- """关闭窗口时自动保存所有用户话术"""
- if self.current_user:
- self.save_current_user_scripts()
- try:
- with open("user_scripts_backup.json", "w", encoding="utf-8") as f:
- json.dump(self.user_scripts, f, ensure_ascii=False, indent=2)
- self.log_text.append("[系统] 程序退出,已自动保存所有话术配置")
- except:
- pass
- event.accept()
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- window = MainWindow()
- window.show()
- sys.exit(app.exec_())
|