From 77feaffa48f0798a9a10db0ed22f6097829b0944 Mon Sep 17 00:00:00 2001 From: Supercmd Date: Sat, 16 May 2026 08:27:41 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=90=8D?= =?UTF-8?q?=E5=8D=95=E8=A1=A8=E6=A0=BC=E6=90=9C=E7=B4=A2=E7=AD=9B=E9=80=89?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=20(#232)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在点名表格和抽奖表格中添加搜索栏,支持按关键词实时筛选表格行。 - 点名表格:支持按学号、姓名、性别、小组、标签筛选 - 抽奖表格:支持按序号、奖品、权重、标签、数量筛选 - 使用 SearchLineEdit 组件,带防抖处理(300ms) - 添加中/英/日三语国际化翻译 - 刷新数据后自动重新应用搜索过滤 Closes #232 --- app/Language/modules/list_management.py | 48 ++++++++++++++++++ .../settings/list_management/lottery_table.py | 49 +++++++++++++++++++ .../list_management/roll_call_table.py | 49 +++++++++++++++++++ 3 files changed, 146 insertions(+) diff --git a/app/Language/modules/list_management.py b/app/Language/modules/list_management.py index 36ea586f..5f9d56f2 100644 --- a/app/Language/modules/list_management.py +++ b/app/Language/modules/list_management.py @@ -122,6 +122,14 @@ "name": "选择班级", "description": "选择要显示的点名班级", }, + "search": { + "name": "搜索名单", + "description": "在名单中搜索学生", + }, + "search_placeholder": { + "name": "输入学号、姓名、性别、小组或标签进行筛选", + "description": "搜索框占位符", + }, "HeaderLabels": { "name": ["存在", "学号", "姓名", "性别", "小组", "标签"], "description": "点名表格的列标题", @@ -151,6 +159,14 @@ "name": "Select class", "description": "Select the class to show", }, + "search": { + "name": "Search list", + "description": "Search students in the list", + }, + "search_placeholder": { + "name": "Filter by ID, name, gender, group or tags", + "description": "Search box placeholder", + }, "HeaderLabels": { "name": { "0": "Exist", @@ -190,6 +206,14 @@ "name": "クラスを選択", "description": "表示する点呼クラスを選択", }, + "search": { + "name": "リスト検索", + "description": "リスト内の学生を検索", + }, + "search_placeholder": { + "name": "学籍番号、氏名、性別、グループ、タグで絞り込み", + "description": "検索ボックスのプレースホルダー", + }, "HeaderLabels": { "name": ["存在", "学籍番号", "氏名", "性別", "グループ", "タグ"], "description": "点呼テーブルの列タイトル", @@ -311,6 +335,14 @@ "name": "选择奖池", "description": "选择要显示的抽奖奖池", }, + "search": { + "name": "搜索名单", + "description": "在名单中搜索奖品", + }, + "search_placeholder": { + "name": "输入序号、奖品、权重、标签或数量进行筛选", + "description": "搜索框占位符", + }, "HeaderLabels": { "name": ["存在", "序号", "奖品", "权重", "标签", "数量"], "description": "抽奖表格的列标题", @@ -340,6 +372,14 @@ "name": "Select pool", "description": "Select the pool to show", }, + "search": { + "name": "Search list", + "description": "Search prizes in the list", + }, + "search_placeholder": { + "name": "Filter by serial, prize, weight, tags or count", + "description": "Search box placeholder", + }, "HeaderLabels": { "name": { "0": "Exist", @@ -379,6 +419,14 @@ "name": "賞プールを選択", "description": "表示する抽選賞プールを選択", }, + "search": { + "name": "リスト検索", + "description": "リスト内の賞品を検索", + }, + "search_placeholder": { + "name": "番号、賞品、重み、タグ、数量で絞り込み", + "description": "検索ボックスのプレースホルダー", + }, "HeaderLabels": { "name": ["存在", "番号", "賞品", "重み", "タグ", "数量"], "description": "抽選テーブルの列タイトル", diff --git a/app/view/settings/list_management/lottery_table.py b/app/view/settings/list_management/lottery_table.py index 100d9764..8626ddf3 100644 --- a/app/view/settings/list_management/lottery_table.py +++ b/app/view/settings/list_management/lottery_table.py @@ -35,9 +35,17 @@ def __init__(self, parent=None): self.parent = parent self.setTitle(get_content_name_async("lottery_table", "title")) self.setBorderRadius(8) + self._search_timer = QTimer(self) + self._search_timer.setSingleShot(True) + self._search_timer.setInterval(300) + self._search_timer.timeout.connect(self._apply_search_filter) + # 创建抽奖名单选择区域 QTimer.singleShot(APPLY_DELAY, self.create_lottery_selection) + # 创建搜索栏 + QTimer.singleShot(APPLY_DELAY, self.create_search_bar) + # 创建表格区域 QTimer.singleShot(APPLY_DELAY, self.create_table) @@ -86,6 +94,46 @@ def create_lottery_selection(self): self.lottery_comboBox, ) + def create_search_bar(self): + """创建搜索栏""" + self.search_line_edit = SearchLineEdit() + self.search_line_edit.setPlaceholderText( + get_content_name_async("lottery_table", "search_placeholder") + ) + self.search_line_edit.setClearButtonEnabled(True) + self.search_line_edit.textChanged.connect(self._on_search_text_changed) + + self.addGroup( + get_theme_icon("ic_fluent_search_20_filled"), + get_content_name_async("lottery_table", "search"), + get_content_description_async("lottery_table", "search"), + self.search_line_edit, + ) + + def _on_search_text_changed(self): + """搜索文本变化时启动防抖计时器""" + self._search_timer.start() + + def _apply_search_filter(self): + """根据搜索关键词过滤表格行""" + if not hasattr(self, "table") or self.table is None: + return + + keyword = self.search_line_edit.text().strip().lower() + + for row in range(self.table.rowCount()): + if not keyword: + self.table.setRowHidden(row, False) + continue + + matched = False + for col in range(self.table.columnCount()): + item = self.table.item(row, col) + if item and keyword in item.text().lower(): + matched = True + break + self.table.setRowHidden(row, not matched) + def create_table(self): """创建表格区域""" # 创建表格 @@ -283,6 +331,7 @@ def refresh_data(self): finally: # 恢复信号 self.table.blockSignals(False) + self._apply_search_filter() def save_table_data(self, row, col): """保存表格编辑的数据""" diff --git a/app/view/settings/list_management/roll_call_table.py b/app/view/settings/list_management/roll_call_table.py index b9df18e7..6b5de6f6 100644 --- a/app/view/settings/list_management/roll_call_table.py +++ b/app/view/settings/list_management/roll_call_table.py @@ -35,9 +35,17 @@ def __init__(self, parent=None): self.parent = parent self.setTitle(get_content_name_async("roll_call_table", "title")) self.setBorderRadius(8) + self._search_timer = QTimer(self) + self._search_timer.setSingleShot(True) + self._search_timer.setInterval(300) + self._search_timer.timeout.connect(self._apply_search_filter) + # 创建班级选择区域 QTimer.singleShot(APPLY_DELAY, self.create_class_selection) + # 创建搜索栏 + QTimer.singleShot(APPLY_DELAY, self.create_search_bar) + # 创建表格区域 QTimer.singleShot(APPLY_DELAY, self.create_table) @@ -80,6 +88,46 @@ def create_class_selection(self): self.class_comboBox, ) + def create_search_bar(self): + """创建搜索栏""" + self.search_line_edit = SearchLineEdit() + self.search_line_edit.setPlaceholderText( + get_content_name_async("roll_call_table", "search_placeholder") + ) + self.search_line_edit.setClearButtonEnabled(True) + self.search_line_edit.textChanged.connect(self._on_search_text_changed) + + self.addGroup( + get_theme_icon("ic_fluent_search_20_filled"), + get_content_name_async("roll_call_table", "search"), + get_content_description_async("roll_call_table", "search"), + self.search_line_edit, + ) + + def _on_search_text_changed(self): + """搜索文本变化时启动防抖计时器""" + self._search_timer.start() + + def _apply_search_filter(self): + """根据搜索关键词过滤表格行""" + if not hasattr(self, "table") or self.table is None: + return + + keyword = self.search_line_edit.text().strip().lower() + + for row in range(self.table.rowCount()): + if not keyword: + self.table.setRowHidden(row, False) + continue + + matched = False + for col in range(self.table.columnCount()): + item = self.table.item(row, col) + if item and keyword in item.text().lower(): + matched = True + break + self.table.setRowHidden(row, not matched) + def create_table(self): """创建表格区域""" # 创建表格 @@ -272,6 +320,7 @@ def refresh_data(self): finally: # 恢复信号 self.table.blockSignals(False) + self._apply_search_filter() def save_table_data(self, row, col): """保存表格编辑的数据""" From 747d2ee43c7ac0e793c3a1eb9c3e332701d051d8 Mon Sep 17 00:00:00 2001 From: Supercmd Date: Sat, 16 May 2026 09:11:05 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E8=AE=B0=E5=BD=95=E5=AF=BC=E5=87=BA=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=20(#232)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在点名历史记录和抽奖历史记录表格中添加导出按钮, 支持将当前表格数据导出为 xlsx、csv、txt 格式。 - 点名历史记录:支持导出全部记录、按时间查看、个人统计三种模式的数据 - 抽奖历史记录:支持导出全部记录、按时间查看、奖品统计三种模式的数据 - 导出内容与用户当前看到的表格一致(包括筛选和排序状态) - 添加中/英/日三语国际化翻译 - 添加 QFileDialog 翻译配置 Closes #232 --- .gitignore | 1 + app/Language/modules/history.py | 48 ++++++ app/Language/modules/list_management.py | 72 ++++++++- .../settings/history/lottery_history_table.py | 147 ++++++++++++++++++ .../history/roll_call_history_table.py | 147 ++++++++++++++++++ pyproject.toml | 2 +- uv.lock | 14 +- 7 files changed, 417 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 10549a19..cbea4b57 100644 --- a/.gitignore +++ b/.gitignore @@ -184,6 +184,7 @@ cython_debug/ # VSCode .vscode/settings.json +.vscode/launch.json /.trae /app/config /app/config diff --git a/app/Language/modules/history.py b/app/Language/modules/history.py index 44ddae27..f645d346 100644 --- a/app/Language/modules/history.py +++ b/app/Language/modules/history.py @@ -226,6 +226,14 @@ "name": "公平抽取", "description": "公平抽取模式", }, + "export": { + "name": "导出记录", + "description": "将当前表格数据导出为文件", + }, + "export_button": { + "name": "导出", + "description": "导出按钮文本", + }, }, "EN_US": { "title": { @@ -320,6 +328,14 @@ "name": "Fair pick", "description": "Fair picking mode", }, + "export": { + "name": "Export records", + "description": "Export current table data to a file", + }, + "export_button": { + "name": "Export", + "description": "Export button text", + }, "select_weight": { "name": "Show weight", "description": "Whether to show weight in table", @@ -419,6 +435,14 @@ "name": "公平抽出", "description": "公平抽出モード", }, + "export": { + "name": "記録をエクスポート", + "description": "現在のテーブルデータをファイルにエクスポート", + }, + "export_button": { + "name": "エクスポート", + "description": "エクスポートボタンテキスト", + }, "select_weight": { "name": "重みを表示", "description": "テーブルに重みを表示するかどうか", @@ -460,6 +484,14 @@ "name": ["抽奖时间", "抽取数量", "课程", "权重"], "description": "抽奖历史记录表格列标题(单次记录)", }, + "export": { + "name": "导出记录", + "description": "将当前表格数据导出为文件", + }, + "export_button": { + "name": "导出", + "description": "导出按钮文本", + }, }, "EN_US": { "title": { @@ -508,6 +540,14 @@ }, "description": "Lottery history table title column header weight (individual)", }, + "export": { + "name": "Export records", + "description": "Export current table data to a file", + }, + "export_button": { + "name": "Export", + "description": "Export button text", + }, }, "JA_JP": { "title": { @@ -556,5 +596,13 @@ }, "description": "抽選履歴テーブルの列タイトル(単一記録)", }, + "export": { + "name": "記録をエクスポート", + "description": "現在のテーブルデータをファイルにエクスポート", + }, + "export_button": { + "name": "エクスポート", + "description": "エクスポートボタンテキスト", + }, }, } diff --git a/app/Language/modules/list_management.py b/app/Language/modules/list_management.py index 5f9d56f2..2722d6f2 100644 --- a/app/Language/modules/list_management.py +++ b/app/Language/modules/list_management.py @@ -797,7 +797,17 @@ "name": "Excel 文件 (*.xlsx);;CSV 文件 (*.csv);;TXT 文件(仅姓名) (*.txt)", "description": "保存学生名单对话框过滤器", }, - } + }, + "export_history": { + "caption": { + "name": "导出点名记录", + "description": "导出点名记录对话框标题", + }, + "filter": { + "name": "Excel 文件 (*.xlsx);;CSV 文件 (*.csv);;TXT 文件 (*.txt)", + "description": "导出点名记录对话框过滤器", + }, + }, }, "lottery": { "export_prize_name": { @@ -809,7 +819,17 @@ "name": "Excel 文件 (*.xlsx);;CSV 文件 (*.csv);;TXT 文件(仅奖品名) (*.txt)", "description": "保存奖品名单对话框过滤器", }, - } + }, + "export_history": { + "caption": { + "name": "导出抽奖记录", + "description": "导出抽奖记录对话框标题", + }, + "filter": { + "name": "Excel 文件 (*.xlsx);;CSV 文件 (*.csv);;TXT 文件 (*.txt)", + "description": "导出抽奖记录对话框过滤器", + }, + }, }, }, "EN_US": { @@ -823,7 +843,17 @@ "name": "Excel files (*.xlsx);;CSV files (*.csv);;TXT files (name only) (*.txt)", "description": "Save student list dialog filter", }, - } + }, + "export_history": { + "caption": { + "name": "Export picking records", + "description": "Export picking records dialog title", + }, + "filter": { + "name": "Excel files (*.xlsx);;CSV files (*.csv);;TXT files (*.txt)", + "description": "Export picking records dialog filter", + }, + }, }, "lottery": { "export_prize_name": { @@ -835,7 +865,17 @@ "name": "Excel files (*.xlsx);;CSV files (*.csv);;TXT files (only prizes) (*.txt)", "description": "Save prize list dialog filter", }, - } + }, + "export_history": { + "caption": { + "name": "Export lottery records", + "description": "Export lottery records dialog title", + }, + "filter": { + "name": "Excel files (*.xlsx);;CSV files (*.csv);;TXT files (*.txt)", + "description": "Export lottery records dialog filter", + }, + }, }, }, "JA_JP": { @@ -849,7 +889,17 @@ "name": "Excelファイル (*.xlsx);;CSVファイル (*.csv);;TXTファイル(氏名のみ) (*.txt)", "description": "学生リスト保存ダイアログフィルター", }, - } + }, + "export_history": { + "caption": { + "name": "点呼記録をエクスポート", + "description": "点呼記録エクスポートダイアログタイトル", + }, + "filter": { + "name": "Excelファイル (*.xlsx);;CSVファイル (*.csv);;TXTファイル (*.txt)", + "description": "点呼記録エクスポートダイアログフィルター", + }, + }, }, "lottery": { "export_prize_name": { @@ -861,7 +911,17 @@ "name": "Excelファイル (*.xlsx);;CSVファイル (*.csv);;TXTファイル(賞品名のみ) (*.txt)", "description": "賞品リスト保存ダイアログフィルター", }, - } + }, + "export_history": { + "caption": { + "name": "抽選記録をエクスポート", + "description": "抽選記録エクスポートダイアログタイトル", + }, + "filter": { + "name": "Excelファイル (*.xlsx);;CSVファイル (*.csv);;TXTファイル (*.txt)", + "description": "抽選記録エクスポートダイアログフィルター", + }, + }, }, }, } diff --git a/app/view/settings/history/lottery_history_table.py b/app/view/settings/history/lottery_history_table.py index 0037c0c2..182bf84d 100644 --- a/app/view/settings/history/lottery_history_table.py +++ b/app/view/settings/history/lottery_history_table.py @@ -141,6 +141,20 @@ def create_pool_selection(self): self.mode_subject_widget, ) + # 创建导出按钮 + self.export_button = PushButton( + get_content_name_async("lottery_history_table", "export_button") + ) + self.export_button.setFixedWidth(120) + self.export_button.clicked.connect(self.export_history_data) + + self.addGroup( + get_theme_icon("ic_fluent_document_arrow_down_20_filled"), + get_content_name_async("lottery_history_table", "export"), + get_content_description_async("lottery_history_table", "export"), + self.export_button, + ) + def create_table(self): """创建表格区域""" # 创建表格 @@ -977,3 +991,136 @@ def _update_subject_list(self): except Exception as e: logger.exception(f"更新课程列表失败: {e}") self.available_subjects = [] + + def export_history_data(self): + """导出当前表格数据到文件""" + if not self.current_pool_name: + return + + if self.table.rowCount() == 0: + return + + file_path, selected_filter = QFileDialog.getSaveFileName( + self, + get_any_position_value_async( + "qfiledialog", + "lottery", + "export_history", + "caption", + "name", + ), + f"{self.current_pool_name}_抽奖记录-SecRandom", + get_any_position_value_async( + "qfiledialog", + "lottery", + "export_history", + "filter", + "name", + ), + ) + + if not file_path: + return + + export_type = ( + "excel" + if "Excel 文件 (*.xlsx)" in selected_filter + else "csv" + if "CSV 文件 (*.csv)" in selected_filter + else "txt" + ) + + if export_type == "excel" and not file_path.endswith(".xlsx"): + file_path += ".xlsx" + elif export_type == "csv" and not file_path.endswith(".csv"): + file_path += ".csv" + elif export_type == "txt" and not file_path.endswith(".txt"): + file_path += ".txt" + + try: + headers = [] + for col in range(self.table.columnCount()): + header_item = self.table.horizontalHeaderItem(col) + headers.append(header_item.text() if header_item else f"列{col}") + + export_data = [] + for row in range(self.table.rowCount()): + row_data = {} + for col in range(self.table.columnCount()): + item = self.table.item(row, col) + row_data[headers[col]] = item.text() if item else "" + export_data.append(row_data) + + if export_type == "excel": + import pandas as pd + + df = pd.DataFrame(export_data) + df.to_excel(file_path, index=False, engine="openpyxl") + elif export_type == "csv": + import pandas as pd + + df = pd.DataFrame(export_data) + df.to_csv(file_path, index=False, encoding="utf-8-sig") + else: + name_col_idx = None + for col in range(self.table.columnCount()): + header_item = self.table.horizontalHeaderItem(col) + if header_item and header_item.text() in ("名称", "Name"): + name_col_idx = col + break + + with open(file_path, "w", encoding="utf-8") as f: + for row in range(self.table.rowCount()): + if name_col_idx is not None: + item = self.table.item(row, name_col_idx) + f.write(f"{item.text()}\n" if item else "\n") + else: + for col in range(self.table.columnCount()): + item = self.table.item(row, col) + f.write(f"{item.text()}\t" if item else "\t") + f.write("\n") + + config = NotificationConfig( + title=get_any_position_value_async( + "notification", + "lottery", + "export", + "title", + "success", + "name", + ), + content=get_any_position_value_async( + "notification", + "lottery", + "export", + "content", + "success", + "name", + ).format(path=file_path), + duration=3000, + ) + show_notification(NotificationType.SUCCESS, config, parent=self) + logger.info(f"抽奖历史记录导出成功: {file_path}") + + except Exception as e: + logger.exception(f"导出抽奖历史记录失败: {e}") + config = NotificationConfig( + title=get_any_position_value_async( + "notification", + "lottery", + "export", + "title", + "failure", + "name", + ), + content=get_any_position_value_async( + "notification", + "lottery", + "export", + "content", + "error", + "name", + ).format(message=str(e)), + duration=3000, + ) + show_notification(NotificationType.ERROR, config, parent=self) diff --git a/app/view/settings/history/roll_call_history_table.py b/app/view/settings/history/roll_call_history_table.py index 63cbcde4..f49841a3 100644 --- a/app/view/settings/history/roll_call_history_table.py +++ b/app/view/settings/history/roll_call_history_table.py @@ -147,6 +147,20 @@ def create_class_selection(self): self.mode_subject_widget, ) + # 创建导出按钮 + self.export_button = PushButton( + get_content_name_async("roll_call_history_table", "export_button") + ) + self.export_button.setFixedWidth(120) + self.export_button.clicked.connect(self.export_history_data) + + self.addGroup( + get_theme_icon("ic_fluent_document_arrow_down_20_filled"), + get_content_name_async("roll_call_history_table", "export"), + get_content_description_async("roll_call_history_table", "export"), + self.export_button, + ) + def create_table(self): """创建表格区域""" # 创建表格 @@ -1143,3 +1157,136 @@ def update_table_headers(self): self.table.setColumnCount(len(headers)) self.table.setHorizontalHeaderLabels(headers) + + def export_history_data(self): + """导出当前表格数据到文件""" + if not self.current_class_name: + return + + if self.table.rowCount() == 0: + return + + file_path, selected_filter = QFileDialog.getSaveFileName( + self, + get_any_position_value_async( + "qfiledialog", + "roll_call", + "export_history", + "caption", + "name", + ), + f"{self.current_class_name}_点名记录-SecRandom", + get_any_position_value_async( + "qfiledialog", + "roll_call", + "export_history", + "filter", + "name", + ), + ) + + if not file_path: + return + + export_type = ( + "excel" + if "Excel 文件 (*.xlsx)" in selected_filter + else "csv" + if "CSV 文件 (*.csv)" in selected_filter + else "txt" + ) + + if export_type == "excel" and not file_path.endswith(".xlsx"): + file_path += ".xlsx" + elif export_type == "csv" and not file_path.endswith(".csv"): + file_path += ".csv" + elif export_type == "txt" and not file_path.endswith(".txt"): + file_path += ".txt" + + try: + headers = [] + for col in range(self.table.columnCount()): + header_item = self.table.horizontalHeaderItem(col) + headers.append(header_item.text() if header_item else f"列{col}") + + export_data = [] + for row in range(self.table.rowCount()): + row_data = {} + for col in range(self.table.columnCount()): + item = self.table.item(row, col) + row_data[headers[col]] = item.text() if item else "" + export_data.append(row_data) + + if export_type == "excel": + import pandas as pd + + df = pd.DataFrame(export_data) + df.to_excel(file_path, index=False, engine="openpyxl") + elif export_type == "csv": + import pandas as pd + + df = pd.DataFrame(export_data) + df.to_csv(file_path, index=False, encoding="utf-8-sig") + else: + name_col_idx = None + for col in range(self.table.columnCount()): + header_item = self.table.horizontalHeaderItem(col) + if header_item and header_item.text() in ("姓名", "Name"): + name_col_idx = col + break + + with open(file_path, "w", encoding="utf-8") as f: + for row in range(self.table.rowCount()): + if name_col_idx is not None: + item = self.table.item(row, name_col_idx) + f.write(f"{item.text()}\n" if item else "\n") + else: + for col in range(self.table.columnCount()): + item = self.table.item(row, col) + f.write(f"{item.text()}\t" if item else "\t") + f.write("\n") + + config = NotificationConfig( + title=get_any_position_value_async( + "notification", + "roll_call", + "export", + "title", + "success", + "name", + ), + content=get_any_position_value_async( + "notification", + "roll_call", + "export", + "content", + "success", + "name", + ).format(path=file_path), + duration=3000, + ) + show_notification(NotificationType.SUCCESS, config, parent=self) + logger.info(f"点名历史记录导出成功: {file_path}") + + except Exception as e: + logger.exception(f"导出点名历史记录失败: {e}") + config = NotificationConfig( + title=get_any_position_value_async( + "notification", + "roll_call", + "export", + "title", + "failure", + "name", + ), + content=get_any_position_value_async( + "notification", + "roll_call", + "export", + "content", + "error", + "name", + ).format(message=str(e)), + duration=3000, + ) + show_notification(NotificationType.ERROR, config, parent=self) diff --git a/pyproject.toml b/pyproject.toml index abbc07fa..6b69bead 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ requires-python = "==3.13.5" dependencies = [ # === UI / 界面 === - "PySide6-Fluent-Widgets==1.11.0", + "PySide6-Fluent-Widgets==1.11.2", "pyside6>6.6.3.1", "pysidesix-frameless-window>=0.7.4", "darkdetect==0.8.0", diff --git a/uv.lock b/uv.lock index 06468682..46c3842e 100644 --- a/uv.lock +++ b/uv.lock @@ -3602,30 +3602,30 @@ wheels = [ [[package]] name = "pyside6-fluent-widgets" -version = "1.11.0" +version = "1.11.2" source = { registry = "https://mirrors.aliyun.com/pypi/simple" } dependencies = [ { name = "darkdetect" }, { name = "pyside6" }, { name = "pysidesix-frameless-window" }, ] -sdist = { url = "https://mirrors.aliyun.com/pypi/packages/f7/79/89ede298a98552317b71c199f7001f728401ea5e5f05ccece5cb390f71f6/pyside6_fluent_widgets-1.11.0.tar.gz", hash = "sha256:ac74b7d08fd78b06304416ac6d62cc47818949d79605899eb64c53bd99c6c322" } +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/f1/22/01a72ab00873fac2575e8045cd4dfcb003afc0f0764982c706817be5629a/pyside6_fluent_widgets-1.11.2.tar.gz", hash = "sha256:cf49ff76b9b2ad1dc24f071a1b2a3f5f0a67d7adf655915071ddfb7342caf175" } wheels = [ - { url = "https://mirrors.aliyun.com/pypi/packages/3e/4a/49d2b3b7bb35e006de4a3a2192c78a005cd1d44bd18e33ae12fc6cb3672c/pyside6_fluent_widgets-1.11.0-py3-none-any.whl", hash = "sha256:d13763304137fb843b955dbaad9e0ffafca306018769d0ea9094b9f707ff7938" }, + { url = "https://mirrors.aliyun.com/pypi/packages/78/cb/ad62113621b3e619e4fa069a383e5060a6169e93a9df73f15f2cf68bdf5a/pyside6_fluent_widgets-1.11.2-py3-none-any.whl", hash = "sha256:7d3bb3d79b743cbb16eef0a0471f1d0c47d6c8c8dd78402820bd3cdae4da1ea0" }, ] [[package]] name = "pysidesix-frameless-window" -version = "0.7.7" +version = "0.8.1" source = { registry = "https://mirrors.aliyun.com/pypi/simple" } dependencies = [ { name = "pycocoa", marker = "sys_platform == 'darwin'" }, { name = "pyobjc", marker = "sys_platform == 'darwin'" }, { name = "pywin32", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://mirrors.aliyun.com/pypi/packages/cf/ba/c41e25e8884224d15b14ffad34c921f350a6b0cfce823f150a514a0d3788/pysidesix_frameless_window-0.7.7.tar.gz", hash = "sha256:4f975bae89a6ebd8babeed693341f242b268c94816e81602e026eb95703d4eb4" } +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/e7/44/ee4b9ead46ec5fcc4d9a303f6ac82cb17b0e188bfe629ef962c4046cded5/pysidesix_frameless_window-0.8.1.tar.gz", hash = "sha256:95eefa64abdaca9d730bc097fd39e2cd07d3443a47a1645cc936a0076996d7cd" } wheels = [ - { url = "https://mirrors.aliyun.com/pypi/packages/70/e2/fb1e36cbd8ed5c0db161ace24ad40b5278ac9af6fecc9bcd6ab68712fb1c/pysidesix_frameless_window-0.7.7-py3-none-any.whl", hash = "sha256:cd6b2961cc30d9290f84462bc59de674bea6a72df5d36fb57d5fb49d660c13e8" }, + { url = "https://mirrors.aliyun.com/pypi/packages/60/02/13dc76880e9f54102b8d4859a1a14061c6914c12d8c8554dc49ef55ab209/pysidesix_frameless_window-0.8.1-py3-none-any.whl", hash = "sha256:0445e7ce095c3631893ec54edb470a47c2bb05ea64db736f446211550b7c2237" }, ] [[package]] @@ -3888,7 +3888,7 @@ requires-dist = [ { name = "pypng", specifier = "~=0.20220715.0" }, { name = "pyqrcode", specifier = "~=1.2.1" }, { name = "pyside6", specifier = ">6.6.3.1" }, - { name = "pyside6-fluent-widgets", specifier = "==1.11.0" }, + { name = "pyside6-fluent-widgets", specifier = "==1.11.2" }, { name = "pysidesix-frameless-window", specifier = ">=0.7.4" }, { name = "pytest", marker = "extra == 'dev'", specifier = ">=6.0" }, { name = "pythonnet", specifier = ">=3.0.5" }, From 2c5f549bc99ffa6fb5456a14ab0842d135a8d482 Mon Sep 17 00:00:00 2001 From: Supercmd Date: Sat, 16 May 2026 09:20:19 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=E7=BC=BA=E5=A4=B1?= =?UTF-8?q?=E7=9A=84=20config=20=E5=AF=BC=E5=85=A5=E4=BF=AE=E5=A4=8D=20Not?= =?UTF-8?q?ificationConfig=20=E6=9C=AA=E5=AE=9A=E4=B9=89=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/view/settings/history/lottery_history_table.py | 1 + app/view/settings/history/roll_call_history_table.py | 1 + 2 files changed, 2 insertions(+) diff --git a/app/view/settings/history/lottery_history_table.py b/app/view/settings/history/lottery_history_table.py index 182bf84d..39b34c78 100644 --- a/app/view/settings/history/lottery_history_table.py +++ b/app/view/settings/history/lottery_history_table.py @@ -13,6 +13,7 @@ from app.tools.variable import * from app.tools.path_utils import * from app.tools.personalised import * +from app.tools.config import * from app.tools.settings_default import * from app.tools.settings_access import * from app.Language.obtain_language import * diff --git a/app/view/settings/history/roll_call_history_table.py b/app/view/settings/history/roll_call_history_table.py index f49841a3..9b99ddf7 100644 --- a/app/view/settings/history/roll_call_history_table.py +++ b/app/view/settings/history/roll_call_history_table.py @@ -13,6 +13,7 @@ from app.tools.variable import * from app.tools.path_utils import * from app.tools.personalised import * +from app.tools.config import * from app.tools.settings_default import * from app.tools.settings_access import * from app.Language.obtain_language import * From a3018b62e1e0174cd5f6d2e981bf0dd7386210a0 Mon Sep 17 00:00:00 2001 From: Supercmd Date: Sat, 16 May 2026 09:22:55 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20=E4=BD=BF=E7=94=A8=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=89=A9=E5=B1=95=E5=90=8D=E5=8C=B9=E9=85=8D=E6=9B=BF=E4=BB=A3?= =?UTF-8?q?=E7=A1=AC=E7=BC=96=E7=A0=81=E4=B8=AD=E6=96=87=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=B2=E5=88=A4=E6=96=AD=E5=AF=BC=E5=87=BA=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复非中文语言环境下导出格式判断失败的问题。 将 'Excel 文件 (*.xlsx)' 改为 '.xlsx' 匹配, 确保所有语言下都能正确识别导出格式。 --- app/view/settings/history/lottery_history_table.py | 4 ++-- app/view/settings/history/roll_call_history_table.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/view/settings/history/lottery_history_table.py b/app/view/settings/history/lottery_history_table.py index 39b34c78..51336cb9 100644 --- a/app/view/settings/history/lottery_history_table.py +++ b/app/view/settings/history/lottery_history_table.py @@ -1025,9 +1025,9 @@ def export_history_data(self): export_type = ( "excel" - if "Excel 文件 (*.xlsx)" in selected_filter + if ".xlsx" in selected_filter else "csv" - if "CSV 文件 (*.csv)" in selected_filter + if ".csv" in selected_filter else "txt" ) diff --git a/app/view/settings/history/roll_call_history_table.py b/app/view/settings/history/roll_call_history_table.py index 9b99ddf7..55e98d6a 100644 --- a/app/view/settings/history/roll_call_history_table.py +++ b/app/view/settings/history/roll_call_history_table.py @@ -1191,9 +1191,9 @@ def export_history_data(self): export_type = ( "excel" - if "Excel 文件 (*.xlsx)" in selected_filter + if ".xlsx" in selected_filter else "csv" - if "CSV 文件 (*.csv)" in selected_filter + if ".csv" in selected_filter else "txt" )