第一步优化勾选功能
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
BIN
dist/多多自动化发文助手.exe
vendored
BIN
dist/多多自动化发文助手.exe
vendored
Binary file not shown.
227
gui_app.py
227
gui_app.py
@@ -51,6 +51,7 @@ class MainWindow(QMainWindow):
|
||||
self.page_size = 20
|
||||
self.current_page = 1
|
||||
self.page_row_indices = []
|
||||
self.filtered_config_indices = None # 文本/状态筛选后的配置索引,None 表示未筛选(显示全部)
|
||||
self.use_model_view = False
|
||||
# 批量任务队列相关
|
||||
self.batch_task_queue = [] # 任务队列
|
||||
@@ -1000,16 +1001,14 @@ class MainWindow(QMainWindow):
|
||||
|
||||
def _clear_filter_and_selection(self):
|
||||
"""清空筛选并取消所有勾选"""
|
||||
# 取消所有勾选
|
||||
for config in self.configs:
|
||||
config['勾选'] = False
|
||||
# 取消全选复选框
|
||||
if hasattr(self, 'table_select_all_checkbox'):
|
||||
self.table_select_all_checkbox.setChecked(False)
|
||||
# 清空搜索框(会触发 filter_table 显示所有行)
|
||||
self._current_status_filter = None
|
||||
self.filtered_config_indices = None
|
||||
# 清空搜索框会触发 filter_table(""),从而刷新为全量显示
|
||||
self.table_search_input.setText("")
|
||||
# 刷新表格显示
|
||||
self.update_table()
|
||||
self._update_checked_count()
|
||||
self._show_infobar("info", "已清空", "筛选条件和勾选已清空")
|
||||
|
||||
@@ -1018,97 +1017,24 @@ class MainWindow(QMainWindow):
|
||||
is_checked = self.table_select_all_checkbox.isChecked()
|
||||
visible_count = 0
|
||||
|
||||
# 检查是否有筛选条件(搜索关键词或状态筛选)
|
||||
has_search_filter = hasattr(self, 'table_search_input') and self.table_search_input.text().strip()
|
||||
has_status_filter = hasattr(self, '_current_status_filter') and self._current_status_filter
|
||||
|
||||
if has_search_filter or has_status_filter:
|
||||
# 有筛选条件:只操作筛选后的数据
|
||||
# 遍历所有配置,只操作符合筛选条件的
|
||||
for config_index, config in enumerate(self.configs):
|
||||
# 检查是否符合搜索筛选(支持多关键词,所有关键词都要匹配)
|
||||
if has_search_filter:
|
||||
search_text = self.table_search_input.text().strip()
|
||||
terms_raw = [t for t in search_text.split() if t]
|
||||
if terms_raw:
|
||||
# 根据当前视图类型选择列索引映射
|
||||
if self.use_model_view:
|
||||
column_index = self._filter_model_column_index()
|
||||
col_key_map = {
|
||||
0: '多多id', 1: '序号', 2: '话题', 3: '定时发布',
|
||||
4: '间隔时间', 5: '达人链接', 6: '执行人', 7: '情况', 8: '文件路径'
|
||||
}
|
||||
else:
|
||||
column_index = self._filter_column_index()
|
||||
col_key_map = {
|
||||
1: '多多id', 2: '序号', 3: '话题', 4: '定时发布',
|
||||
5: '间隔时间', 6: '达人链接', 7: '执行人', 8: '情况', 9: '文件路径'
|
||||
}
|
||||
match = False
|
||||
if column_index >= 0:
|
||||
# 按指定列筛选
|
||||
if column_index in col_key_map:
|
||||
cell_value = str(config.get(col_key_map[column_index], '')).lower()
|
||||
# 所有关键词都要在单元格中
|
||||
if all(term.lower() in cell_value for term in terms_raw):
|
||||
match = True
|
||||
else:
|
||||
# 全列搜索
|
||||
all_text = ' '.join([str(config.get(k, '')) for k in
|
||||
['多多id', '序号', '话题', '定时发布', '间隔时间',
|
||||
'达人链接', '执行人', '情况', '文件路径']]).lower()
|
||||
# 所有关键词都要在文本中
|
||||
if all(term.lower() in all_text for term in terms_raw):
|
||||
match = True
|
||||
if not match:
|
||||
continue
|
||||
|
||||
# 检查是否符合状态筛选(使用与 _filter_by_status 相同的匹配逻辑)
|
||||
if has_status_filter:
|
||||
config_status = config.get('情况', '待执行')
|
||||
if self._current_status_filter == "成功":
|
||||
status_match = "完成" in config_status or "成功" in config_status
|
||||
elif self._current_status_filter == "失败":
|
||||
status_match = "失败" in config_status or "错误" in config_status
|
||||
else:
|
||||
status_match = self._current_status_filter in config_status
|
||||
if not status_match:
|
||||
continue
|
||||
|
||||
# 符合筛选条件,更新勾选状态
|
||||
self.configs[config_index]['勾选'] = is_checked
|
||||
visible_count += 1
|
||||
# 有筛选时只操作筛选结果(filtered_config_indices),否则操作全部
|
||||
indices = getattr(self, 'filtered_config_indices', None)
|
||||
if indices is not None:
|
||||
for config_index in indices:
|
||||
if 0 <= config_index < len(self.configs):
|
||||
self.configs[config_index]['勾选'] = is_checked
|
||||
visible_count += 1
|
||||
else:
|
||||
# 无筛选条件:操作所有数据(跨页)
|
||||
for config_index in range(len(self.configs)):
|
||||
self.configs[config_index]['勾选'] = is_checked
|
||||
visible_count += 1
|
||||
|
||||
# 刷新表格显示
|
||||
self.update_table()
|
||||
self._update_checked_count()
|
||||
# 更新状态统计
|
||||
self._update_status_statistics()
|
||||
|
||||
# 重新应用筛选和高亮(保持原有的筛选状态)
|
||||
if has_search_filter:
|
||||
if hasattr(self, 'table_search_input') and self.table_search_input.text().strip():
|
||||
self._suppress_filter_clear_once = True
|
||||
self.filter_table(self.table_search_input.text())
|
||||
elif has_status_filter:
|
||||
# 重新应用状态筛选(隐藏不匹配的行,使用与 _filter_by_status 相同的匹配逻辑)
|
||||
for row in range(self.config_table.rowCount()):
|
||||
if row < len(self.page_row_indices):
|
||||
config_index = self.page_row_indices[row]
|
||||
if config_index < len(self.configs):
|
||||
config_status = self.configs[config_index].get('情况', '待执行')
|
||||
# 使用相同的状态匹配逻辑
|
||||
if self._current_status_filter == "成功":
|
||||
status_match = "完成" in config_status or "成功" in config_status
|
||||
elif self._current_status_filter == "失败":
|
||||
status_match = "失败" in config_status or "错误" in config_status
|
||||
else:
|
||||
status_match = self._current_status_filter in config_status
|
||||
self.config_table.setRowHidden(row, not status_match)
|
||||
|
||||
if is_checked:
|
||||
self._show_infobar("success", "提示", f"已勾选 {visible_count} 行(跨页操作)")
|
||||
@@ -1720,10 +1646,10 @@ class MainWindow(QMainWindow):
|
||||
suppress_clear = getattr(self, "_suppress_filter_clear_once", False)
|
||||
if suppress_clear:
|
||||
self._suppress_filter_clear_once = False
|
||||
# 清除状态筛选,确保每次筛选都基于全量数据
|
||||
# 清除状态筛选,确保文本筛选基于全量数据
|
||||
if hasattr(self, '_current_status_filter') and self._current_status_filter:
|
||||
self._current_status_filter = None
|
||||
# 先显示所有行,再根据文本筛选
|
||||
self.filtered_config_indices = None
|
||||
if not self.use_model_view and hasattr(self, 'config_table'):
|
||||
for row in range(self.config_table.rowCount()):
|
||||
self.config_table.setRowHidden(row, False)
|
||||
@@ -1763,10 +1689,15 @@ class MainWindow(QMainWindow):
|
||||
self.table_proxy.setFilterKeyColumn(column_index)
|
||||
self.table_proxy.setFilterRegularExpression(regex)
|
||||
return
|
||||
if not self.config_table or self.config_table.rowCount() == 0:
|
||||
if not self.config_table:
|
||||
return
|
||||
# 表格列与 config 键的对应(列 1~9)
|
||||
_table_config_keys = ('多多id', '序号', '话题', '定时发布', '间隔时间', '达人链接', '执行人', '情况', '文件路径')
|
||||
if not keyword_raw:
|
||||
# 清空筛选
|
||||
# 清空筛选:在全量数据上显示,并清除高亮
|
||||
self.filtered_config_indices = None
|
||||
self.current_page = 1
|
||||
self.update_table()
|
||||
for row in range(self.config_table.rowCount()):
|
||||
for col in range(self.config_table.columnCount()):
|
||||
item = self.config_table.item(row, col)
|
||||
@@ -1776,13 +1707,25 @@ class MainWindow(QMainWindow):
|
||||
self.table_match_rows = []
|
||||
self.table_match_index = -1
|
||||
return
|
||||
# 在全量 configs 上计算匹配的配置索引(不限于当前页)
|
||||
terms_raw = [t for t in keyword_raw.split() if t]
|
||||
keyword = keyword_raw.lower()
|
||||
terms_lower = [t.lower() for t in terms_raw]
|
||||
column_index = self._filter_column_index()
|
||||
match_count = 0
|
||||
matched_rows = []
|
||||
matching_indices = []
|
||||
for i, config in enumerate(self.configs):
|
||||
if column_index >= 1 and column_index <= 9:
|
||||
key = _table_config_keys[column_index - 1]
|
||||
cell_text = str(config.get(key, ''))
|
||||
else:
|
||||
cell_text = ' '.join(str(config.get(k, '')) for k in _table_config_keys)
|
||||
cell_compare = cell_text.lower()
|
||||
if all(term in cell_compare for term in terms_lower):
|
||||
matching_indices.append(i)
|
||||
self.filtered_config_indices = matching_indices
|
||||
self.current_page = 1
|
||||
self.update_table()
|
||||
# 当前页均为匹配行,应用高亮
|
||||
for row in range(self.config_table.rowCount()):
|
||||
match = False
|
||||
for col in range(self.config_table.columnCount()):
|
||||
if column_index >= 0 and col != column_index:
|
||||
try:
|
||||
@@ -1797,27 +1740,13 @@ class MainWindow(QMainWindow):
|
||||
if item:
|
||||
cell_text = item.text()
|
||||
cell_compare = cell_text.lower()
|
||||
if keyword:
|
||||
terms = [t.lower() for t in terms_raw]
|
||||
term_hit = all(term in cell_compare for term in terms)
|
||||
if term_hit:
|
||||
match = True
|
||||
if self.table_highlight.isChecked():
|
||||
item.setBackground(self._highlight_color())
|
||||
match_count += 1
|
||||
else:
|
||||
item.setBackground(self._default_color())
|
||||
if all(term in cell_compare for term in terms_lower) and self.table_highlight.isChecked():
|
||||
item.setBackground(self._highlight_color())
|
||||
else:
|
||||
item.setBackground(self._default_color())
|
||||
except RuntimeError:
|
||||
# item 已被删除,跳过
|
||||
continue
|
||||
only_match = self.table_only_match.isChecked() if hasattr(self, 'table_only_match') else False
|
||||
self.config_table.setRowHidden(row, (not match) if (keyword and only_match) else False)
|
||||
if keyword and match:
|
||||
matched_rows.append(row)
|
||||
# 更新匹配行列表
|
||||
self.table_match_rows = matched_rows
|
||||
self.table_match_rows = list(range(self.config_table.rowCount()))
|
||||
self.table_match_index = -1
|
||||
|
||||
def next_table_match(self):
|
||||
@@ -2128,61 +2057,47 @@ class MainWindow(QMainWindow):
|
||||
self.config_table.setRowHidden(row, False)
|
||||
|
||||
def _filter_by_status(self, status):
|
||||
"""按状态筛选表格行"""
|
||||
if not hasattr(self, 'config_table') or self.config_table.rowCount() == 0:
|
||||
"""按状态筛选表格行(在全量数据上计算,分页显示筛选结果)"""
|
||||
if not getattr(self, 'configs', None) or not self.configs:
|
||||
self._show_infobar("warning", "提示", "暂无数据")
|
||||
return
|
||||
|
||||
# 清除文本筛选,确保每次筛选都基于全量数据
|
||||
if hasattr(self, 'table_search_input') and self.table_search_input.text().strip():
|
||||
self.table_search_input.blockSignals(True)
|
||||
self.table_search_input.clear()
|
||||
self.table_search_input.blockSignals(False)
|
||||
# 清除高亮和显示所有行
|
||||
for row in range(self.config_table.rowCount()):
|
||||
for col in range(self.config_table.columnCount()):
|
||||
item = self.config_table.item(row, col)
|
||||
if item:
|
||||
item.setBackground(self._default_color())
|
||||
self.config_table.setRowHidden(row, False)
|
||||
self.filtered_config_indices = None
|
||||
self.table_match_rows = []
|
||||
self.table_match_index = -1
|
||||
|
||||
# 切换筛选状态
|
||||
current_filter = getattr(self, '_current_status_filter', None)
|
||||
if current_filter == status:
|
||||
# 再次点击同一状态,取消筛选,显示全部
|
||||
self._current_status_filter = None
|
||||
self._show_all_rows()
|
||||
self.filtered_config_indices = None
|
||||
self.current_page = 1
|
||||
self.update_table()
|
||||
self._show_infobar("success", "提示", "已显示全部记录")
|
||||
return
|
||||
|
||||
self._current_status_filter = status
|
||||
visible_count = 0
|
||||
total_count = self.config_table.rowCount()
|
||||
|
||||
for row in range(total_count):
|
||||
item = self.config_table.item(row, 8) # 第8列是"情况"列(第0列为勾选框)
|
||||
if item:
|
||||
cell_text = item.text()
|
||||
# 根据状态匹配
|
||||
if status == "成功":
|
||||
match = "完成" in cell_text or "成功" in cell_text
|
||||
elif status == "失败":
|
||||
match = "失败" in cell_text or "错误" in cell_text
|
||||
else:
|
||||
match = status in cell_text
|
||||
|
||||
self.config_table.setRowHidden(row, not match)
|
||||
if match:
|
||||
visible_count += 1
|
||||
# 在全量 configs 上计算匹配的配置索引
|
||||
matching_indices = []
|
||||
for i, config in enumerate(self.configs):
|
||||
config_status = str(config.get('情况', ''))
|
||||
if status == "成功":
|
||||
match = "完成" in config_status or "成功" in config_status
|
||||
elif status == "失败":
|
||||
match = "失败" in config_status or "错误" in config_status
|
||||
else:
|
||||
self.config_table.setRowHidden(row, True)
|
||||
|
||||
if visible_count == 0:
|
||||
match = status in config_status
|
||||
if match:
|
||||
matching_indices.append(i)
|
||||
self.filtered_config_indices = matching_indices
|
||||
self.current_page = 1
|
||||
self.update_table()
|
||||
if not matching_indices:
|
||||
self._show_infobar("warning", "提示", f"没有{status}的记录")
|
||||
else:
|
||||
self._show_infobar("success", "筛选", f"已筛选出 {visible_count} 条{status}记录,再次点击取消筛选")
|
||||
self._show_infobar("success", "筛选", f"已筛选出 {len(matching_indices)} 条{status}记录,再次点击取消筛选")
|
||||
|
||||
def _update_status_statistics(self):
|
||||
"""更新状态统计(成功/失败/待执行数量)- 统计所有配置的真实状态
|
||||
@@ -2968,11 +2883,13 @@ class MainWindow(QMainWindow):
|
||||
self._sync_configs_from_table()
|
||||
|
||||
self.is_updating_table = True
|
||||
total_rows = len(self.configs)
|
||||
# 使用筛选后的索引或全部索引进行分页(筛选在全量数据上计算,分页只切当前页)
|
||||
effective_indices = self.filtered_config_indices if getattr(self, 'filtered_config_indices', None) is not None else list(range(len(self.configs)))
|
||||
total_rows = len(effective_indices)
|
||||
# 设置最小显示行数,即使没有数据也显示空行
|
||||
min_display_rows = 15 # 最少显示15行
|
||||
|
||||
if total_rows > 1000:
|
||||
if len(self.configs) > 1000:
|
||||
self._setup_model_view()
|
||||
self.is_updating_table = False
|
||||
return
|
||||
@@ -2990,7 +2907,7 @@ class MainWindow(QMainWindow):
|
||||
self.current_page = total_pages
|
||||
start = (self.current_page - 1) * self.page_size
|
||||
end = min(start + self.page_size, total_rows)
|
||||
self.page_row_indices = list(range(start, end))
|
||||
self.page_row_indices = list(effective_indices[start:end])
|
||||
|
||||
# 临时禁用排序,防止填充数据时自动排序打乱顺序
|
||||
self.config_table.setSortingEnabled(False)
|
||||
@@ -3226,12 +3143,14 @@ class MainWindow(QMainWindow):
|
||||
self.log_text.append(f" · {s}")
|
||||
if len(no_match_log) > 20:
|
||||
self.log_text.append(f" ... 还有 {len(no_match_log) - 20} 行")
|
||||
total_rows = len(self.configs)
|
||||
self.log_text.append("=" * 50)
|
||||
self.log_text.append(f"更新完成!总计: {rows_with_files}/{len(self.configs)} 行匹配到文件,共 {total_found_files} 个文件")
|
||||
self.log_text.append(f"更新完成!数据 {total_rows} 条,文件 {total_found_files} 个,匹配 {rows_with_files} 条")
|
||||
|
||||
self.update_status_label.setText(f"已更新: {rows_with_files}行,{total_found_files}个文件")
|
||||
status_msg = f"数据 {total_rows} 条,文件 {total_found_files} 个,匹配 {rows_with_files} 条"
|
||||
self.update_status_label.setText(status_msg)
|
||||
self.update_status_label.setStyleSheet("color: #4CAF50; font-size: 10px;")
|
||||
self.set_status_cards(update_text=f"已更新: {rows_with_files}行")
|
||||
self.set_status_cards(update_text=status_msg)
|
||||
self._update_status_statistics()
|
||||
|
||||
# 更新映射
|
||||
@@ -3254,7 +3173,7 @@ class MainWindow(QMainWindow):
|
||||
|
||||
self.log_text.append("=" * 50)
|
||||
self._show_infobar("success", "成功",
|
||||
f"文件查找完成:{rows_with_files}行匹配,共 {total_found_files} 个文件")
|
||||
f"数据 {total_rows} 条,文件 {total_found_files} 个,匹配 {rows_with_files} 条")
|
||||
return
|
||||
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user