diff --git a/data_management/app.py b/data_management/app.py index 5db42d0..75a98f8 100644 --- a/data_management/app.py +++ b/data_management/app.py @@ -96,6 +96,7 @@ class DataManagementApp: on_download_history_callback=self._on_download_history, on_export_callback=self._on_export, on_settings_callback=self._on_settings, + on_item_click_callback=lambda name: self.filter_panel.set_goods_name_and_query(name), width=RIGHT_PANEL_WIDTH ) self.statistics_panel.pack(side="right", fill="y", padx=(5, 0)) diff --git a/data_management/database/mysql_manager.py b/data_management/database/mysql_manager.py index 45aa217..3f6b1bb 100644 --- a/data_management/database/mysql_manager.py +++ b/data_management/database/mysql_manager.py @@ -270,7 +270,7 @@ class MySQLManager: month_start = today_start.replace(day=1) month_count = base_query.filter(Model.create_time >= month_start).count() - # TOP 10物品统计 + # 全部物品统计(按数量降序) from sqlalchemy import func top_items = session.query( Model.goods_name, @@ -289,7 +289,6 @@ class MySQLManager: top_items = top_items.group_by(Model.goods_name)\ .order_by(func.count(Model.id).desc())\ - .limit(10)\ .all() return { diff --git a/data_management/ui/filter_panel.py b/data_management/ui/filter_panel.py index f0ede9f..6651f9f 100644 --- a/data_management/ui/filter_panel.py +++ b/data_management/ui/filter_panel.py @@ -276,3 +276,9 @@ class FilterPanel(ctk.CTkFrame): self.query_button.configure(state="disabled", text="查询中...") else: self.query_button.configure(state="normal", text="查询") + + def set_goods_name_and_query(self, goods_name: str): + """从排行榜点击物品名称时,填入筛选框并触发查询""" + self.goods_search_entry.delete(0, 'end') + self.goods_search_entry.insert(0, goods_name) + self._on_query() diff --git a/data_management/ui/statistics_panel.py b/data_management/ui/statistics_panel.py index d51e53c..0b05b34 100644 --- a/data_management/ui/statistics_panel.py +++ b/data_management/ui/statistics_panel.py @@ -15,6 +15,7 @@ class StatisticsPanel(ctk.CTkFrame): on_download_history_callback: Callable, on_export_callback: Callable, on_settings_callback: Callable, + on_item_click_callback: Optional[Callable] = None, **kwargs ): super().__init__(parent, **kwargs) @@ -23,6 +24,7 @@ class StatisticsPanel(ctk.CTkFrame): self.on_download_history_callback = on_download_history_callback self.on_export_callback = on_export_callback self.on_settings_callback = on_settings_callback + self.on_item_click_callback = on_item_click_callback self._create_widgets() @@ -130,13 +132,13 @@ class StatisticsPanel(ctk.CTkFrame): separator2 = ctk.CTkFrame(time_frame, height=2) separator2.pack(fill="x", pady=10, padx=15) - # ==================== TOP 10物品排行 ==================== + # ==================== 物品排行(全部) ==================== top_frame = ctk.CTkFrame(self) top_frame.pack(fill="both", expand=True, padx=15, pady=(0, 10)) top_title = ctk.CTkLabel( top_frame, - text="TOP 10 物品排行", + text="物品排行(全部)", font=("Arial", 12, "bold") ) top_title.pack(pady=(10, 5), padx=10) @@ -212,7 +214,7 @@ class StatisticsPanel(ctk.CTkFrame): - today_count: 今日数量 - week_count: 本周数量 - month_count: 本月数量 - - top_items: TOP 10列表 [{'name': str, 'count': int}, ...] + - top_items: 全部物品列表 [{'name': str, 'count': int}, ...] """ # 查询结果 total_count = stats.get('total_count', 0) @@ -232,7 +234,7 @@ class StatisticsPanel(ctk.CTkFrame): self._update_top_items(stats.get('top_items', [])) def _update_top_items(self, top_items: list): - """更新TOP 10排行榜""" + """更新物品排行(全部)""" # 清空现有内容 for widget in self.top_scroll.winfo_children(): widget.destroy() @@ -247,7 +249,7 @@ class StatisticsPanel(ctk.CTkFrame): no_data_label.pack(pady=10) return - # 显示TOP 10 + # 显示全部物品 for i, item in enumerate(top_items, 1): item_frame = ctk.CTkFrame(self.top_scroll) item_frame.pack(fill="x", pady=2, padx=5) @@ -261,15 +263,32 @@ class StatisticsPanel(ctk.CTkFrame): ) rank_label.pack(side="left", padx=(5, 2)) - # 物品名称 + # 物品名称(可点击筛选) name_label = ctk.CTkLabel( item_frame, text=item['name'], font=("Arial", 10), - anchor="w" + anchor="w", + cursor="hand2" # 鼠标悬浮时显示手型 ) name_label.pack(side="left", fill="x", expand=True, padx=5) + # 绑定点击与悬浮事件 + if self.on_item_click_callback: + item_name = item['name'] + name_label.bind( + "", + lambda e, name=item_name: self.on_item_click_callback(name) + ) + name_label.bind( + "", + lambda e, lbl=name_label: lbl.configure(text_color="#4FC3F7") + ) + name_label.bind( + "", + lambda e, lbl=name_label: lbl.configure(text_color=ctk.ThemeManager.theme["CTkLabel"]["text_color"]) + ) + # 数量 count_label = ctk.CTkLabel( item_frame, @@ -291,6 +310,6 @@ class StatisticsPanel(ctk.CTkFrame): self.week_label.configure(text="本周: 0 张") self.month_label.configure(text="本月: 0 张") - # 清空TOP 10 + # 清空全部物品排行 for widget in self.top_scroll.winfo_children(): widget.destroy()