From 2193f11e03751772c7b02a8e9c4dd43e895d30b0 Mon Sep 17 00:00:00 2001 From: 27942 <1313123@342> Date: Sat, 24 Jan 2026 18:13:30 +0800 Subject: [PATCH] =?UTF-8?q?gui=20=E7=AC=AC=E4=B8=80=E7=89=88=E5=AE=8C?= =?UTF-8?q?=E6=95=B4=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gui_app.py | 344 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 246 insertions(+), 98 deletions(-) diff --git a/gui_app.py b/gui_app.py index 18ab26b..2d9b6ba 100644 --- a/gui_app.py +++ b/gui_app.py @@ -12,7 +12,7 @@ from PyQt5.QtWidgets import ( QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QFileDialog, QTableWidgetItem, QMessageBox, QDateTimeEdit, QGridLayout, QStackedWidget, QButtonGroup, - QStyle, QComboBox, QFrame, QShortcut, QMenu, + QStyle, QComboBox, QFrame, QShortcut, QMenu, QAbstractButton, QAbstractItemView, QTableView, QStyledItemDelegate, QStyleOptionProgressBar, QStyleOptionButton, QHeaderView, QTabWidget, QSplitter, QSizePolicy @@ -638,6 +638,9 @@ class ConfigTableModel(QAbstractTableModel): key = mapping.get(col, "") if role == Qt.DisplayRole: return str(config.get(key, "")) if key else "" + elif role == Qt.TextAlignmentRole: + # 所有单元格居中对齐 + return Qt.AlignCenter elif role == Qt.ToolTipRole: # 为达人链接和文件路径列提供 tooltip 显示完整内容 if col in (5, 8) and key: @@ -691,9 +694,8 @@ class ConfigTableModel(QAbstractTableModel): class TableActionDelegate(QStyledItemDelegate): """Model/View 操作列 + 进度列 delegate""" - def __init__(self, parent, on_edit, on_delete): + def __init__(self, parent, on_delete): super().__init__(parent) - self.on_edit = on_edit self.on_delete = on_delete def paint(self, painter, option, index): @@ -716,16 +718,10 @@ class TableActionDelegate(QStyledItemDelegate): return if index.column() == 10: rect = option.rect - btn_w = (rect.width() - 12) // 2 - edit_rect = rect.adjusted(6, 4, -rect.width() + btn_w + 6, -4) - delete_rect = rect.adjusted(6 + btn_w + 6, 4, -6, -4) - edit_btn = QStyleOptionButton() - edit_btn.rect = edit_rect - edit_btn.text = "编辑" + delete_rect = rect.adjusted(6, 4, -6, -4) delete_btn = QStyleOptionButton() delete_btn.rect = delete_rect delete_btn.text = "删除" - QApplication.style().drawControl(QStyle.CE_PushButton, edit_btn, painter) QApplication.style().drawControl(QStyle.CE_PushButton, delete_btn, painter) return super().paint(painter, option, index) @@ -735,12 +731,7 @@ class TableActionDelegate(QStyledItemDelegate): return super().editorEvent(event, model, option, index) if event.type() == event.MouseButtonRelease: rect = option.rect - btn_w = (rect.width() - 12) // 2 - edit_rect = rect.adjusted(6, 4, -rect.width() + btn_w + 6, -4) - delete_rect = rect.adjusted(6 + btn_w + 6, 4, -6, -4) - if edit_rect.contains(event.pos()): - self.on_edit(index) - return True + delete_rect = rect.adjusted(6, 4, -6, -4) if delete_rect.contains(event.pos()): self.on_delete(index) return True @@ -964,11 +955,11 @@ class MainWindow(QMainWindow): import_row = QHBoxLayout() import_row.addWidget(QLabel("Excel文件:")) self.excel_path_input = LineEdit() + self.excel_path_input.setReadOnly(True) + self.excel_path_input.setPlaceholderText("点击导入按钮选择Excel配置文件") import_row.addWidget(self.excel_path_input) - self.excel_browse_btn = PushButton("浏览") - self.excel_browse_btn.clicked.connect(self.browse_excel) - import_row.addWidget(self.excel_browse_btn) - self.import_btn = PrimaryPushButton("导入") + self.import_btn = PrimaryPushButton("导入配置") + self.import_btn.setToolTip("选择Excel文件并导入配置") self.import_btn.clicked.connect(self.import_excel) import_row.addWidget(self.import_btn) self.download_template_btn = PushButton("下载模板") @@ -1047,6 +1038,13 @@ class MainWindow(QMainWindow): table_title = QLabel("配置列表(从Excel导入后显示,可直接在表格中编辑)") table_title.setFont(QFont("Microsoft YaHei", 11, QFont.Bold)) table_layout.addWidget(table_title) + self.table_edit_hint = QLabel("编辑模式:当前行已高亮,其它行已锁定。修改后点击“确认”保存,点击“退出”还原。") + self.table_edit_hint.setVisible(False) + self.table_edit_hint.setStyleSheet( + "background-color: #fff7ed; color: #9a3412; " + "border: 1px solid #fed7aa; border-radius: 6px; padding: 6px 8px;" + ) + table_layout.addWidget(self.table_edit_hint) search_row = QHBoxLayout() self.table_search_input = LineEdit() @@ -1143,8 +1141,8 @@ class MainWindow(QMainWindow): self.config_table.horizontalHeader().setSortIndicatorShown(True) self.config_table.verticalHeader().setVisible(False) self.config_table.verticalHeader().setDefaultSectionSize(42) - # 设置表格编辑触发方式:双击进入编辑(单击只选择行) - self.config_table.setEditTriggers(TableWidget.DoubleClicked) + # 禁用直接编辑,只能通过编辑按钮进入编辑模式 + self.config_table.setEditTriggers(TableWidget.NoEditTriggers) self.config_table.setSelectionBehavior(QAbstractItemView.SelectRows) self.config_table.setSelectionMode(QAbstractItemView.ExtendedSelection) self.config_table.setContextMenuPolicy(Qt.CustomContextMenu) @@ -1385,6 +1383,54 @@ class MainWindow(QMainWindow): if current_item: self.config_table.closePersistentEditor(current_item) self.config_table.setCurrentItem(None) + # 恢复为只读模式 + self.config_table.setEditTriggers(TableWidget.NoEditTriggers) + self._cleanup_edit_mode_state() + + def _set_row_highlight(self, row, enabled): + """高亮/取消高亮某一行""" + highlight_color = QColor(255, 247, 216) + for col in range(9): + item = self.config_table.item(row, col) + if not item: + continue + if enabled: + item.setBackground(highlight_color) + else: + item.setData(Qt.BackgroundRole, None) + + def _set_other_rows_locked(self, edit_row, locked): + """锁定/解锁编辑行以外的行""" + for r in range(self.config_table.rowCount()): + if r == edit_row: + # 编辑行保持可用 + continue + # 操作列按钮禁用/启用 + action_widget = self.config_table.cellWidget(r, 10) + if action_widget: + action_widget.setEnabled(not locked) + # 数据列禁用/启用 + for col in range(9): + item = self.config_table.item(r, col) + if not item: + continue + if locked: + item.setFlags(item.flags() & ~Qt.ItemIsEnabled) + else: + item.setFlags((item.flags() | Qt.ItemIsEnabled) & ~Qt.ItemIsEditable) + + def _cleanup_edit_mode_state(self): + """清理编辑态UI状态""" + edit_row = getattr(self, '_editing_row', None) + if edit_row is None: + return + self._set_row_highlight(edit_row, False) + self._set_other_rows_locked(edit_row, False) + self._editing_row = None + if getattr(self, "table_edit_hint", None): + self.table_edit_hint.setVisible(False) + if hasattr(self, '_edit_selection_mode_backup'): + self.config_table.setSelectionMode(self._edit_selection_mode_backup) def on_table_item_changed(self, item): """表格内容变更回调""" @@ -1420,6 +1466,14 @@ class MainWindow(QMainWindow): # 确保标志被重置 self.is_updating_table = False + def _create_centered_item(self, text): + """创建居中对齐的表格单元格""" + item = QTableWidgetItem(str(text)) + item.setTextAlignment(Qt.AlignCenter) + # 默认不可编辑,必须通过编辑按钮进入编辑模式 + item.setFlags(item.flags() & ~Qt.ItemIsEditable) + return item + def _set_status_item(self, row, text): """设置状态列图标与文本""" try: @@ -1427,6 +1481,8 @@ class MainWindow(QMainWindow): self.config_table.itemChanged.disconnect(self.on_table_item_changed) try: item = QTableWidgetItem(text) + item.setTextAlignment(Qt.AlignCenter) # 居中对齐 + item.setFlags(item.flags() & ~Qt.ItemIsEditable) if "完成" in text or "成功" in text: item.setIcon(self.style().standardIcon(QStyle.SP_DialogApplyButton)) elif "失败" in text or "错误" in text: @@ -1466,28 +1522,142 @@ class MainWindow(QMainWindow): self.config_table.setCellWidget(row, 9, progress) def _set_action_buttons(self, row, config_index): - """设置操作列按钮""" + """设置操作列按钮(编辑和删除)""" wrapper = QWidget() layout = QHBoxLayout(wrapper) layout.setContentsMargins(4, 0, 4, 0) + layout.setSpacing(4) edit_btn = PushButton("编辑") + edit_btn.setFixedWidth(50) delete_btn = PushButton("删除") + delete_btn.setFixedWidth(50) # 使用默认参数捕获当前值,避免闭包问题 - edit_btn.clicked.connect(lambda checked, r=row: self._enter_edit_mode(r)) + edit_btn.clicked.connect(lambda checked, r=row, idx=config_index: self._enter_edit_mode(r, idx)) delete_btn.clicked.connect(lambda checked, idx=config_index: self.delete_row_by_index(idx)) layout.addWidget(edit_btn) layout.addWidget(delete_btn) self.config_table.setCellWidget(row, 10, wrapper) - def _enter_edit_mode(self, row): - """进入指定行的编辑模式""" + def _set_edit_mode_buttons(self, row, config_index): + """设置编辑模式按钮(确认和退出)""" + wrapper = QWidget() + layout = QHBoxLayout(wrapper) + layout.setContentsMargins(4, 0, 4, 0) + layout.setSpacing(4) + confirm_btn = PushButton("确认") + confirm_btn.setFixedWidth(50) + cancel_btn = PushButton("退出") + cancel_btn.setFixedWidth(50) + # 使用默认参数捕获当前值 + confirm_btn.clicked.connect(lambda checked, r=row, idx=config_index: self._confirm_edit(r, idx)) + cancel_btn.clicked.connect(lambda checked, r=row, idx=config_index: self._cancel_edit(r, idx)) + layout.addWidget(confirm_btn) + layout.addWidget(cancel_btn) + self.config_table.setCellWidget(row, 10, wrapper) + + def _enter_edit_mode(self, row, config_index): + """进入编辑模式""" if row < 0 or row >= self.config_table.rowCount(): return - # 选中第一个可编辑的单元格(多多ID列) - item = self.config_table.item(row, 0) - if item: - self.config_table.setCurrentItem(item) - self.config_table.editItem(item) + # 允许当前行进入编辑时的交互触发 + if not hasattr(self, '_edit_triggers_backup'): + self._edit_triggers_backup = self.config_table.editTriggers() + self.config_table.setEditTriggers(QAbstractItemView.DoubleClicked | QAbstractItemView.SelectedClicked) + if not hasattr(self, '_edit_selection_mode_backup'): + self._edit_selection_mode_backup = self.config_table.selectionMode() + self.config_table.setSelectionMode(QAbstractItemView.SingleSelection) + self._editing_row = row + # 保存原始数据用于还原 + if not hasattr(self, '_edit_backup'): + self._edit_backup = {} + original_data = {} + for col in range(9): # 前9列是数据列 + item = self.config_table.item(row, col) + original_data[col] = item.text() if item else "" + self._edit_backup[row] = original_data + + # 启用该行的编辑 + for col in range(9): + item = self.config_table.item(row, col) + if item: + item.setFlags(item.flags() | Qt.ItemIsEditable) + # 高亮编辑行并锁定其他行 + self._set_row_highlight(row, True) + self._set_other_rows_locked(row, True) + + # 切换到编辑模式按钮 + self._set_edit_mode_buttons(row, config_index) + + # 自动聚焦第一个可编辑单元格 + first_item = None + for col in range(9): + item = self.config_table.item(row, col) + if item and (item.flags() & Qt.ItemIsEditable): + first_item = item + self.config_table.setCurrentCell(row, col) + break + if first_item: + self.config_table.setFocus(Qt.TabFocusReason) + self.config_table.scrollToItem(first_item, QAbstractItemView.PositionAtCenter) + self.config_table.editItem(first_item) + if self.table_edit_hint: + self.table_edit_hint.setVisible(True) + self._show_infobar("info", "编辑模式", f"正在编辑第 {row + 1} 行,修改后点击确认保存或退出还原") + + def _confirm_edit(self, row, config_index): + """确认编辑并保存""" + if row < 0 or row >= self.config_table.rowCount(): + return + + # 同步表格数据到configs + self._sync_config_from_row(row) + + # 禁用该行的编辑 + for col in range(9): + item = self.config_table.item(row, col) + if item: + item.setFlags(item.flags() & ~Qt.ItemIsEditable) + + # 清除备份 + if hasattr(self, '_edit_backup') and row in self._edit_backup: + del self._edit_backup[row] + + # 恢复操作按钮 + self._set_action_buttons(row, config_index) + self._show_infobar("success", "保存成功", f"第 {row + 1} 行数据已保存") + # 退出编辑模式后恢复为只读 + self.config_table.setEditTriggers(TableWidget.NoEditTriggers) + self._cleanup_edit_mode_state() + + def _cancel_edit(self, row, config_index): + """取消编辑并还原数据""" + if row < 0 or row >= self.config_table.rowCount(): + return + + # 还原原始数据 + if hasattr(self, '_edit_backup') and row in self._edit_backup: + original_data = self._edit_backup[row] + # 临时断开信号防止触发同步 + try: + self.config_table.itemChanged.disconnect(self.on_table_item_changed) + except: + pass + try: + for col, value in original_data.items(): + item = self.config_table.item(row, col) + if item: + item.setText(value) + item.setFlags(item.flags() & ~Qt.ItemIsEditable) + finally: + self.config_table.itemChanged.connect(self.on_table_item_changed) + del self._edit_backup[row] + + # 恢复操作按钮 + self._set_action_buttons(row, config_index) + self._show_infobar("info", "已退出", f"第 {row + 1} 行数据已还原") + # 退出编辑模式后恢复为只读 + self.config_table.setEditTriggers(TableWidget.NoEditTriggers) + self._cleanup_edit_mode_state() def delete_row_by_index(self, row): """删除指定行""" @@ -2061,8 +2231,9 @@ class MainWindow(QMainWindow): """按多多ID应用定时发布+间隔时间规则 规则说明: - 第一种情况:第一条数据有定时时间,有间隔时间5分钟,然后第二条数据的定时时间就是在第一条的上面加5分钟,第三条在第二条定时时间上加5分钟 - 第二种情况:第一条数据没有定时时间,第二条数据有定时时间还有间隔时间5分钟,那么第三条数据在第二条定时时间上加5分钟 + 1. 如果某条有定时时间,就按照定时时间发布,并记录为基准时间 + 2. 如果某条没有定时时间,也没有间隔时间,就是立即发布(不设置定时) + 3. 如果某条没有定时时间,但有间隔时间,就是在上一条发布时间的基础上加上间隔时间发布 注意:按多多ID分组,同一个多多ID的所有数据按行顺序处理 """ @@ -2073,56 +2244,42 @@ class MainWindow(QMainWindow): user_id = config.get("多多id", "") if not user_id: continue - # 只按多多ID分组,不按序号分组 grouped[user_id].append(item) updated_count = 0 for user_id, items in grouped.items(): items.sort(key=lambda x: x["row_idx"]) - base_time = None - interval_seconds = 0 + base_time = None # 上一条的发布时间(基准时间) + for entry in items: config = entry["config"] row_idx = entry["row_idx"] schedule_text = (config.get("定时发布") or "").strip() interval_value = config.get("间隔时间", 0) - # 解析间隔时间 + # 解析间隔时间(分钟转秒) current_interval = self._parse_interval_seconds(interval_value) # 解析定时时间 parsed_time = self._parse_schedule_time(schedule_text) if schedule_text else None - # 情况1:当前条目有定时时间和间隔时间 - # 例如:第1条有定时时间09:00和间隔时间5分钟,或第2条有定时时间09:10和间隔时间5分钟 - if parsed_time and current_interval > 0: - # 设置基准时间和间隔时间,用于后续数据自动计算 + # 情况1:当前条目有定时时间 -> 使用该定时时间,并记录为基准时间 + if parsed_time: base_time = parsed_time - interval_seconds = current_interval - # 不更新当前条目的定时时间(保持用户设置的原值) - # 但更新 base_time 和 interval_seconds 用于后续计算 + # 不修改当前条目的定时时间,保持用户设置的原值 - # 情况2:当前条目有定时时间但没有间隔时间 - # 例如:用户只设置了定时时间,没有设置间隔时间 - elif parsed_time and current_interval == 0: - # 只更新基准时间,清空间隔时间(后续不会自动计算) - base_time = parsed_time - interval_seconds = 0 + # 情况2:当前条目没有定时时间,但有间隔时间 + elif not parsed_time and current_interval > 0: + if base_time: + # 有基准时间 -> 新时间 = 基准时间 + 间隔时间 + base_time = base_time + timedelta(seconds=current_interval) + new_text = self._format_schedule_time(base_time) + config["定时发布"] = new_text + self._update_table_cell(row_idx, 3, new_text, highlight=True) + updated_count += 1 + # 如果没有基准时间,则保持空(立即发布) - # 情况3:当前条目没有定时时间,但存在基准时间和间隔时间 - # 例如:第1条有定时时间09:00和间隔时间5分钟,第2条没有定时时间 -> 第2条自动计算为09:05 - # 或者:第2条有定时时间09:10和间隔时间5分钟,第3条没有定时时间 -> 第3条自动计算为09:15 - elif not parsed_time and base_time and interval_seconds > 0: - # 计算新的定时时间 = 基准时间 + 间隔时间 - base_time = base_time + timedelta(seconds=interval_seconds) - new_text = self._format_schedule_time(base_time) - config["定时发布"] = new_text - self._update_table_cell(row_idx, 3, new_text, highlight=True) - updated_count += 1 - # 注意:base_time 已经更新为新的计算值,用于下一条数据的计算 - - # 情况4:当前条目没有定时时间,也没有基准时间或间隔时间 - # 例如:第1条没有定时时间和间隔时间,第2条也没有 -> 不做任何处理 + # 情况3:当前条目没有定时时间,也没有间隔时间 -> 立即发布(保持空) # 不做任何处理,保持原样 return updated_count @@ -2191,6 +2348,8 @@ class MainWindow(QMainWindow): self.config_table.itemChanged.disconnect(self.on_table_item_changed) try: item = QTableWidgetItem(str(value)) + item.setTextAlignment(Qt.AlignCenter) # 居中对齐 + item.setFlags(item.flags() & ~Qt.ItemIsEditable) if highlight: item.setBackground(QColor("#E6F4FF")) self.config_table.setItem(row, col, item) @@ -2225,6 +2384,8 @@ class MainWindow(QMainWindow): try: # 第7列是"情况"列 status_item = QTableWidgetItem(status) + status_item.setTextAlignment(Qt.AlignCenter) # 居中对齐 + status_item.setFlags(status_item.flags() & ~Qt.ItemIsEditable) # 根据状态设置不同的颜色 if status == "已完成": @@ -2654,10 +2815,7 @@ class MainWindow(QMainWindow): for col, width in widths.items(): if col < self.config_table.columnCount(): self.config_table.setColumnWidth(col, width) - # 设置达人链接列和文件路径列不自动调整宽度 - header = self.config_table.horizontalHeader() - header.setSectionResizeMode(5, QHeaderView.Fixed) # 达人链接列固定宽度 - header.setSectionResizeMode(8, QHeaderView.Fixed) # 文件路径列固定宽度 + # 所有列都可以手动调整宽度(Interactive模式) def _apply_table_view_column_widths(self): """应用 Model/View 列宽""" @@ -2677,11 +2835,7 @@ class MainWindow(QMainWindow): for col, width in widths.items(): if self.table_view.model() and col < self.table_view.model().columnCount(): self.table_view.setColumnWidth(col, width) - # 设置达人链接列和文件路径列固定宽度 - header = self.table_view.horizontalHeader() - if header: - header.setSectionResizeMode(5, QHeaderView.Fixed) # 达人链接列固定宽度 - header.setSectionResizeMode(8, QHeaderView.Fixed) # 文件路径列固定宽度 + # 所有列都可以手动调整宽度(Interactive模式) def _refresh_log_match_selector(self, items): """更新日志匹配下拉""" @@ -2731,14 +2885,6 @@ class MainWindow(QMainWindow): else: InfoBar.error(title=title, content=content, parent=self, position=InfoBarPosition.TOP_RIGHT) - def browse_excel(self): - """浏览Excel文件""" - file_path, _ = QFileDialog.getOpenFileName( - self, "选择Excel文件", "", "Excel文件 (*.xlsx *.xls)" - ) - if file_path: - self.excel_path_input.setText(file_path) - def browse_folder(self): """浏览文件夹""" folder_path = QFileDialog.getExistingDirectory(self, "选择文件夹") @@ -2783,7 +2929,7 @@ class MainWindow(QMainWindow): self.log_text.append(" - 序号: 文件序号,用于匹配文件夹中的文件(如:1-视频名称.mp4)") self.log_text.append(" - 话题: 发布时的话题标签") self.log_text.append(" - 定时发布: 定时发布时间(格式:yyyy-MM-dd HH:mm)") - self.log_text.append(" - 间隔时间: 同一ID下各条目的发布间隔(分钟)") + self.log_text.append(" - 间隔时间: 在上一条基础上延迟的分钟数(无定时时间时生效)") self.log_text.append(" - 达人链接: 达人主页链接") self.log_text.append(" - 执行人: 负责人") self.log_text.append(" - 情况: 执行状态(待执行/执行中/已完成/失败)") @@ -2793,15 +2939,17 @@ class MainWindow(QMainWindow): logger.error(f"保存模板失败: {e}") def import_excel(self): - """导入Excel配置文件""" - excel_path = self.excel_path_input.text().strip() - if not excel_path: - self._show_infobar("warning", "警告", "请先选择Excel文件") - return + """导入Excel配置文件(直接弹出文件选择对话框)""" + # 弹出文件选择对话框 + excel_path, _ = QFileDialog.getOpenFileName( + self, "选择Excel配置文件", "", "Excel文件 (*.xlsx *.xls)" + ) - if not os.path.exists(excel_path): - self._show_infobar("warning", "警告", f"Excel文件不存在: {excel_path}") - return + if not excel_path: + return # 用户取消选择 + + # 显示选择的文件路径 + self.excel_path_input.setText(excel_path) try: # 读取Excel文件,添加更多异常处理 @@ -2917,21 +3065,21 @@ class MainWindow(QMainWindow): self.config_table.setRowCount(len(self.page_row_indices)) for table_row, config_index in enumerate(self.page_row_indices): config = self.configs[config_index] - self.config_table.setItem(table_row, 0, QTableWidgetItem(str(config.get('多多id', '')))) - self.config_table.setItem(table_row, 1, QTableWidgetItem(str(config.get('序号', '')))) - self.config_table.setItem(table_row, 2, QTableWidgetItem(str(config.get('话题', '')))) - self.config_table.setItem(table_row, 3, QTableWidgetItem(str(config.get('定时发布', '')))) - self.config_table.setItem(table_row, 4, QTableWidgetItem(str(config.get('间隔时间', 0)))) + self.config_table.setItem(table_row, 0, self._create_centered_item(str(config.get('多多id', '')))) + self.config_table.setItem(table_row, 1, self._create_centered_item(str(config.get('序号', '')))) + self.config_table.setItem(table_row, 2, self._create_centered_item(str(config.get('话题', '')))) + self.config_table.setItem(table_row, 3, self._create_centered_item(str(config.get('定时发布', '')))) + self.config_table.setItem(table_row, 4, self._create_centered_item(str(config.get('间隔时间', 0)))) # 达人链接列:设置 tooltip 显示完整内容 url_text = str(config.get('达人链接', '')) - url_item = QTableWidgetItem(url_text) + url_item = self._create_centered_item(url_text) url_item.setToolTip(url_text) # 悬停显示完整链接 self.config_table.setItem(table_row, 5, url_item) - self.config_table.setItem(table_row, 6, QTableWidgetItem(str(config.get('执行人', '')))) + self.config_table.setItem(table_row, 6, self._create_centered_item(str(config.get('执行人', '')))) self._set_status_item(table_row, str(config.get('情况', '待执行'))) # 文件路径列(第8列,索引为8),如果配置中没有则显示空,设置 tooltip file_path = str(config.get('文件路径', '')) - file_path_item = QTableWidgetItem(file_path) + file_path_item = self._create_centered_item(file_path) file_path_item.setToolTip(file_path) # 悬停显示完整路径 self.config_table.setItem(table_row, 8, file_path_item) self._set_progress_item(table_row, str(config.get('情况', '待执行')))