增加了查看入库秤上传图片的GUI界面。

This commit is contained in:
2025-11-27 10:46:53 +08:00
parent c74ac621a6
commit 1bedc16bd8
16 changed files with 2703 additions and 0 deletions
+296
View File
@@ -0,0 +1,296 @@
"""
右侧统计面板
"""
import customtkinter as ctk
from typing import Dict, Callable, Optional
class StatisticsPanel(ctk.CTkFrame):
"""右侧统计面板"""
def __init__(
self,
parent,
on_refresh_callback: Callable,
on_download_history_callback: Callable,
on_export_callback: Callable,
on_settings_callback: Callable,
**kwargs
):
super().__init__(parent, **kwargs)
self.on_refresh_callback = on_refresh_callback
self.on_download_history_callback = on_download_history_callback
self.on_export_callback = on_export_callback
self.on_settings_callback = on_settings_callback
self._create_widgets()
def _create_widgets(self):
"""创建UI组件"""
# 标题
title_label = ctk.CTkLabel(
self,
text="统计信息",
font=("Arial", 16, "bold")
)
title_label.pack(pady=(15, 10), padx=15)
# ==================== 当前数据源信息 ====================
datasource_frame = ctk.CTkFrame(self)
datasource_frame.pack(fill="x", padx=15, pady=(0, 10))
datasource_title = ctk.CTkLabel(
datasource_frame,
text="当前数据源",
font=("Arial", 12, "bold")
)
datasource_title.pack(pady=(10, 5), padx=10)
self.datasource_label = ctk.CTkLabel(
datasource_frame,
text="菜品",
font=("Arial", 14, "bold"),
text_color="blue"
)
self.datasource_label.pack(pady=(0, 10), padx=10)
# ==================== 数据统计 ====================
stats_frame = ctk.CTkFrame(self)
stats_frame.pack(fill="x", padx=15, pady=(0, 10))
stats_title = ctk.CTkLabel(
stats_frame,
text="数据统计",
font=("Arial", 12, "bold")
)
stats_title.pack(pady=(10, 5), padx=10)
# 查询结果
self.query_result_label = ctk.CTkLabel(
stats_frame,
text="查询结果: 0 张",
font=("Arial", 11),
anchor="w"
)
self.query_result_label.pack(fill="x", pady=2, padx=15)
# 已选择
self.selected_label = ctk.CTkLabel(
stats_frame,
text="已选择: 0 张",
font=("Arial", 11),
anchor="w"
)
self.selected_label.pack(fill="x", pady=2, padx=15)
# 分隔线
separator1 = ctk.CTkFrame(stats_frame, height=2)
separator1.pack(fill="x", pady=10, padx=15)
# ==================== 时间分布 ====================
time_frame = ctk.CTkFrame(self)
time_frame.pack(fill="x", padx=15, pady=(0, 10))
time_title = ctk.CTkLabel(
time_frame,
text="时间分布",
font=("Arial", 12, "bold")
)
time_title.pack(pady=(10, 5), padx=10)
# 今日
self.today_label = ctk.CTkLabel(
time_frame,
text="今日: 0 张",
font=("Arial", 11),
anchor="w"
)
self.today_label.pack(fill="x", pady=2, padx=15)
# 本周
self.week_label = ctk.CTkLabel(
time_frame,
text="本周: 0 张",
font=("Arial", 11),
anchor="w"
)
self.week_label.pack(fill="x", pady=2, padx=15)
# 本月
self.month_label = ctk.CTkLabel(
time_frame,
text="本月: 0 张",
font=("Arial", 11),
anchor="w"
)
self.month_label.pack(fill="x", pady=2, padx=15)
# 分隔线
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 物品排行",
font=("Arial", 12, "bold")
)
top_title.pack(pady=(10, 5), padx=10)
# 可滚动的排行榜
self.top_scroll = ctk.CTkScrollableFrame(top_frame, height=200)
self.top_scroll.pack(fill="both", expand=True, padx=10, pady=(0, 10))
# ==================== 快捷操作 ====================
actions_frame = ctk.CTkFrame(self)
actions_frame.pack(fill="x", padx=15, pady=(0, 15))
actions_title = ctk.CTkLabel(
actions_frame,
text="快捷操作",
font=("Arial", 12, "bold")
)
actions_title.pack(pady=(10, 5), padx=10)
# 刷新按钮
refresh_btn = ctk.CTkButton(
actions_frame,
text="🔄 刷新",
command=self.on_refresh_callback,
height=30
)
refresh_btn.pack(fill="x", padx=10, pady=2)
# 下载历史按钮
history_btn = ctk.CTkButton(
actions_frame,
text="📜 下载历史",
command=self.on_download_history_callback,
height=30,
fg_color="purple",
hover_color="darkviolet"
)
history_btn.pack(fill="x", padx=10, pady=2)
# 导出按钮
export_btn = ctk.CTkButton(
actions_frame,
text="📊 导出数据",
command=self.on_export_callback,
height=30,
fg_color="orange",
hover_color="darkorange"
)
export_btn.pack(fill="x", padx=10, pady=2)
# 设置按钮
settings_btn = ctk.CTkButton(
actions_frame,
text="⚙️ 设置",
command=self.on_settings_callback,
height=30,
fg_color="gray",
hover_color="darkgray"
)
settings_btn.pack(fill="x", padx=10, pady=(2, 10))
def update_datasource(self, datasource: str):
"""更新当前数据源显示"""
self.datasource_label.configure(text=datasource)
def update_statistics(self, stats: Dict):
"""
更新统计信息
Args:
stats: 统计数据字典,包含:
- total_count: 总数量
- today_count: 今日数量
- week_count: 本周数量
- month_count: 本月数量
- top_items: TOP 10列表 [{'name': str, 'count': int}, ...]
"""
# 查询结果
total_count = stats.get('total_count', 0)
self.query_result_label.configure(text=f"查询结果: {total_count}")
# 时间分布
today_count = stats.get('today_count', 0)
self.today_label.configure(text=f"今日: {today_count}")
week_count = stats.get('week_count', 0)
self.week_label.configure(text=f"本周: {week_count}")
month_count = stats.get('month_count', 0)
self.month_label.configure(text=f"本月: {month_count}")
# TOP 10排行
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()
if not top_items:
no_data_label = ctk.CTkLabel(
self.top_scroll,
text="暂无数据",
font=("Arial", 11),
text_color="gray"
)
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)
# 排名
rank_label = ctk.CTkLabel(
item_frame,
text=f"{i}.",
font=("Arial", 11, "bold"),
width=30
)
rank_label.pack(side="left", padx=(5, 2))
# 物品名称
name_label = ctk.CTkLabel(
item_frame,
text=item['name'],
font=("Arial", 10),
anchor="w"
)
name_label.pack(side="left", fill="x", expand=True, padx=5)
# 数量
count_label = ctk.CTkLabel(
item_frame,
text=f"{item['count']}",
font=("Arial", 10),
text_color="blue"
)
count_label.pack(side="right", padx=5)
def update_selected_count(self, count: int):
"""更新已选择数量"""
self.selected_label.configure(text=f"已选择: {count}")
def clear_statistics(self):
"""清空统计信息"""
self.query_result_label.configure(text="查询结果: 0 张")
self.selected_label.configure(text="已选择: 0 张")
self.today_label.configure(text="今日: 0 张")
self.week_label.configure(text="本周: 0 张")
self.month_label.configure(text="本月: 0 张")
# 清空TOP 10
for widget in self.top_scroll.winfo_children():
widget.destroy()