from sevice.airtight_service import * import threading class State: def __init__(self): self.selected_record = None # 存储选中的记录 self.batch_id = 0 s = State() # 创建 BatteryDatabase 实例 battery_db = BatteryDatabase() def main(page: ft.Page): page.title = "监控系统" # 添加这行代码,设置应用为中文本地化 page.locale = "zh-CN" page.padding = 0 page.bgcolor = ft.Colors.TRANSPARENT # 设置滚动条主题 page.theme = ft.Theme( scrollbar_theme=ft.ScrollbarTheme( track_color=ft.Colors.BLACK38, track_border_color=ft.Colors.GREY_800, thumb_color=ft.Colors.BLUE_700, # thumb_border_color=ft.Colors.BLUE_900, track_visibility=True, thumb_visibility=True, thickness=10, radius=5, main_axis_margin=2, cross_axis_margin=2, ) ) threading.Thread(target=start, args=(page,), daemon=True).start() # 设置窗口大小和禁止调整 page.window.width = 1000 page.window.height = 700 page.window.resizable = False # page.window.maximizable = False # 禁止最大化按钮 # page.window.minimizable = False # 保留最小化 page.update() # ----------------------------------------------------------------------- def on_message(data_list): print('-------------------------') if isinstance(data_list, dict) and 'message_type' in data_list: if data_list['message_type'] == 'data_130': if data_list['payload']: data_table_130_update(data_list['payload']) elif data_list['message_type'] == 'real_time': if data_list['payload']: search_real_data(data_list['payload']) else: print("未知消息格式:", data_list) # if data_list: # search_real_data(data_list) page.pubsub.subscribe(on_message) data_table_130 = ft.DataTable( width=980, # 表格最小宽度,确保列不挤压 columns=[ ft.DataColumn(ft.Text("序号", color=ft.Colors.WHITE, width=20, size=8, no_wrap=False)), ft.DataColumn(ft.Text("箱1", color=ft.Colors.WHITE, width=240, size=12, no_wrap=False)), ft.DataColumn(ft.Text("上面二维码", color=ft.Colors.WHITE, width=110, size=12, no_wrap=False)), ft.DataColumn(ft.Text("下面二维码", color=ft.Colors.WHITE, width=110, size=12, no_wrap=False)), ft.DataColumn(ft.Text("H2", color=ft.Colors.WHITE, width=30, size=12, no_wrap=False)), ft.DataColumn(ft.Text("O2", color=ft.Colors.WHITE, width=30, size=12, no_wrap=False)), ft.DataColumn(ft.Text("厚度", color=ft.Colors.WHITE, width=40, size=12, no_wrap=False)), ], rows=[ ft.DataRow(cells=[ ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=20)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=240)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=110)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=110)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=30)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=30)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=40)), ]), ], ) data_table_130_1 = ft.DataTable( width=980, # 表格最小宽度,确保列不挤压 columns=[ ft.DataColumn(ft.Text("序号", color=ft.Colors.WHITE, width=20, size=8, no_wrap=False)), ft.DataColumn(ft.Text("箱2", color=ft.Colors.WHITE, width=240, size=12, no_wrap=False)), ft.DataColumn(ft.Text("上面二维码", color=ft.Colors.WHITE, width=110, size=12, no_wrap=False)), ft.DataColumn(ft.Text("下面二维码", color=ft.Colors.WHITE, width=110, size=12, no_wrap=False)), ft.DataColumn(ft.Text("H2", color=ft.Colors.WHITE, width=30, size=12, no_wrap=False)), ft.DataColumn(ft.Text("O2", color=ft.Colors.WHITE, width=30, size=12, no_wrap=False)), ft.DataColumn(ft.Text("厚度", color=ft.Colors.WHITE, width=40, size=12, no_wrap=False)), ], rows=[ ft.DataRow(cells=[ ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=20)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=240)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=110)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=110)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=30)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=30)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=40)), ]), ], ) # 创建文本控件 dynamic_text = ft.Text("弹夹码", color=ft.Colors.WHITE, size=14) # 创建 Row content_row = ft.Row([ dynamic_text ], alignment=ft.MainAxisAlignment.START) def data_table_130_update(e): data_list_130 = e data_table_130.rows = [] data_table_130_1.rows = [] # 只更新文本内容,不重新定义布局 dynamic_text.value = data_list_130.get('cah_no', '未知编号') for index, item in enumerate(data_list_130['box_data_1']['battery_data_1']): data_table_130.rows.append( ft.DataRow([ ft.DataCell(ft.Text( str(index + 1), color=ft.Colors.WHITE, width=20, size=12, # 减小字体大小 no_wrap=False # 允许自动换行 )), ft.DataCell(ft.Text( data_list_130['box_data_1']['box_data_1_no'], color=ft.Colors.WHITE, width=240, size=10, no_wrap=False )), ft.DataCell(ft.Text( item.get('Below_QR'), color=ft.Colors.WHITE, width=110, size=12, no_wrap=False )), ft.DataCell(ft.Text( item.get('Up_QR'), color=ft.Colors.WHITE, width=110, size=12, no_wrap=False )), ft.DataCell(ft.Text( item.get('H2'), color=ft.Colors.WHITE, width=30, size=12, no_wrap=False )), ft.DataCell(ft.Text( item.get('02'), color=ft.Colors.WHITE, width=30, size=12, no_wrap=False )), ft.DataCell(ft.Text( str(item.get('thick')), color=ft.Colors.WHITE, width=40, size=12, no_wrap=False )), ]) ) data_table_130_1.rows = [] for index, item in enumerate(data_list_130['box_data_2']['battery_data_2']): data_table_130_1.rows.append( ft.DataRow([ ft.DataCell(ft.Text( str(index + 1), color=ft.Colors.WHITE, width=20, size=12, # 减小字体大小 no_wrap=False # 允许自动换行 )), ft.DataCell(ft.Text( data_list_130['box_data_2']['box_data_2_no'], color=ft.Colors.WHITE, width=240, size=10, no_wrap=False )), ft.DataCell(ft.Text( item.get('Below_QR'), color=ft.Colors.WHITE, width=110, size=12, no_wrap=False )), ft.DataCell(ft.Text( item.get('Up_QR'), color=ft.Colors.WHITE, width=110, size=12, no_wrap=False )), ft.DataCell(ft.Text( item.get('H2'), color=ft.Colors.WHITE, width=30, size=12, no_wrap=False )), ft.DataCell(ft.Text( item.get('02'), color=ft.Colors.WHITE, width=30, size=12, no_wrap=False )), ft.DataCell(ft.Text( str(item.get('thick')), color=ft.Colors.WHITE, width=40, size=12, no_wrap=False )), ]) ) # 更新所有控件 dynamic_text.update() data_table_130.update() data_table_130_1.update() page0 = ft.SafeArea( ft.Column([ ft.Container( content=content_row, padding=20, margin=ft.Margin(20, 10, 20, 0), border=ft.border.all(0.5, ft.Colors.WHITE), bgcolor=ft.Colors.BLACK26, ), ft.Container( content=ft.Column([ # 使用 Row 来左右布局 # 左侧表格 ft.Container( content=ft.ListView( width=980, # 宽度减半,留出间距 height=280, spacing=0, controls=[ ft.Row( scroll=ft.ScrollMode.ALWAYS, controls=[data_table_130] ) ] ), bgcolor=ft.Colors.BLACK26, ), # 右侧表格 ft.Container( content=ft.ListView( width=980, height=280, spacing=0, controls=[ ft.Row( scroll=ft.ScrollMode.ALWAYS, controls=[data_table_130_1] # 可以替换为另一个表格 ) ] ), bgcolor=ft.Colors.BLACK26, ) ], scroll=ft.ScrollMode.AUTO), # 如果需要水平滚动 width=1000, margin=ft.Margin(20, 0, 20, 20), border=ft.border.all(0.5, ft.Colors.WHITE), bgcolor=ft.Colors.BLACK12, ) ]) ) data_table = ft.DataTable( width=900, # 表格最小宽度,确保列不挤压 columns=[ ft.DataColumn(ft.Text("序号", color=ft.Colors.WHITE, width=50, size=12, no_wrap=False)), ft.DataColumn(ft.Text("上面二维码", color=ft.Colors.WHITE, width=150, size=12, no_wrap=False)), ft.DataColumn(ft.Text("下面二维码", color=ft.Colors.WHITE, width=150, size=12, no_wrap=False)), ft.DataColumn(ft.Text("H2", color=ft.Colors.WHITE, width=50, size=12, no_wrap=False)), ft.DataColumn(ft.Text("O2", color=ft.Colors.WHITE, width=50, size=12, no_wrap=False)), ft.DataColumn(ft.Text("厚度", color=ft.Colors.WHITE, width=50, size=12, no_wrap=False)), ], rows=[ ft.DataRow(cells=[ ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=50)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=150)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=150)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=50)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=50)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=50)), ]), ], ) shen7_table = ft.DataTable( width=900, # 表格最小宽度,确保列不挤压 columns=[ ft.DataColumn(ft.Text("低压损", color=ft.Colors.WHITE, size=12, width=400, no_wrap=False)), ft.DataColumn(ft.Text("H2", color=ft.Colors.WHITE, size=12, width=100, no_wrap=False)), ft.DataColumn(ft.Text("O2", color=ft.Colors.WHITE, size=12, width=100, no_wrap=False)), ], rows=[ ft.DataRow(cells=[ ft.DataCell(ft.Text("", color=ft.Colors.WHITE, width=400)), ft.DataCell(ft.Text("", color=ft.Colors.WHITE, width=100)), ft.DataCell(ft.Text("", color=ft.Colors.WHITE, width=100)), ]), ], ) def search_real_data(e): search_data = e shen7_table.rows = [] data_table.rows = [] for item in search_data['shen_7']: shen7_table.rows.append( ft.DataRow([ ft.DataCell(ft.Text( item, color=ft.Colors.WHITE, width=400, size=12, # 减小字体大小 no_wrap=False # 允许自动换行 )), ft.DataCell(ft.Text( item[32:34] + '.' + item[34:36], color=ft.Colors.WHITE, width=100, size=12, no_wrap=False )), ft.DataCell(ft.Text( item[36:38] + '.' + item[38:40], color=ft.Colors.WHITE, width=100, size=12, no_wrap=False )), ]) ) shen7_table.update() for index, item in enumerate(search_data['all']): data_table.rows.append( ft.DataRow([ ft.DataCell(ft.Text( str(index + 1), color=ft.Colors.WHITE, width=50, size=12, # 减小字体大小 no_wrap=False # 允许自动换行 )), ft.DataCell(ft.Text( item.get('top_qr_code'), color=ft.Colors.WHITE, width=150, size=12, no_wrap=False )), ft.DataCell(ft.Text( item.get('bottom_qr_code'), color=ft.Colors.WHITE, width=150, size=12, no_wrap=False )), ft.DataCell(ft.Text( str(item.get('h2_value')), color=ft.Colors.WHITE, width=50, size=12, no_wrap=False )), ft.DataCell(ft.Text( str (item.get('o2_value')), color=ft.Colors.WHITE, width=50, size=12, no_wrap=False )), ft.DataCell(ft.Text( str(item.get('thickness')), color=ft.Colors.WHITE, width=50, size=12, no_wrap=False )), ]) ) data_table.update() # 实时监控页面内容 page1 = ft.SafeArea( ft.Column([ ft.Container( content=ft.ListView( width=1000, height=330, spacing=0, # 行之间无间距,模拟表格紧凑样式 # 内层:水平滚动容器(Row),控制表格列的滚动 controls=[ ft.Row( scroll=ft.ScrollMode.ALWAYS, # 始终显示水平滚动条 controls=[ # 表格内容 shen7_table ] ) ] ), # padding=20, margin=ft.Margin(20, 5, 20, 0), border=ft.border.all(0.5, ft.Colors.WHITE), bgcolor=ft.Colors.BLACK26, # 半透黑色背景,便于在图片上看清 ), # 下方表格区域,带白色边框和外边距,宽度与上方保持一致 ft.Container( content=ft.ListView( width=1000, height=250, spacing=0, # 行之间无间距,模拟表格紧凑样式 # 内层:水平滚动容器(Row),控制表格列的滚动 controls=[ ft.Row( scroll=ft.ScrollMode.ALWAYS, # 始终显示水平滚动条 controls=[ # 表格内容 data_table ] ) ] ), # padding=20, margin=ft.Margin(20, 5, 20, 20), border=ft.border.all(0.5, ft.Colors.WHITE), bgcolor=ft.Colors.BLACK26, # 半透黑色背景,便于在图片上看清 ) ]) ) start_date = ft.ElevatedButton( "请选择起始日期", icon=ft.Icons.CALENDAR_MONTH, width=190, on_click=lambda e: page.open( ft.DatePicker( # first_date=datetime(2000, 10, 1), # last_date=datetime(2099, 10, 1), on_change=handle_change_start, on_dismiss=handle_dismissal, ) ), ) end_date = ft.ElevatedButton( "请选择结束日期", icon=ft.Icons.CALENDAR_MONTH, width=185, on_click=lambda e: page.open( ft.DatePicker( # first_date=datetime(2000, 10, 1), # last_date=datetime(2099, 10, 1), on_change=handle_change_end, on_dismiss=handle_dismissal, ) ), ) histroy_data_table = ft.DataTable( width=900, # 表格最小宽度,确保列不挤压 columns=[ ft.DataColumn(ft.Text("序号", color=ft.Colors.WHITE, width=50, size=12, no_wrap=False)), ft.DataColumn(ft.Text("时间", color=ft.Colors.WHITE, width=50, size=12, no_wrap=False)), ft.DataColumn(ft.Text("查看详情", color=ft.Colors.WHITE, width=50, size=12, no_wrap=False)), ], rows=[ ft.DataRow(cells=[ ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=50)), ft.DataCell(ft.Text(" ", color=ft.Colors.GREEN, width=200)), ft.DataCell(ft.Text(" ", color=ft.Colors.GREEN, width=100)), ]), ], ) # 查看详情按钮点击事件 def view_details(e, record): s.selected_record = record histroy_search_list(record) # 切换到详情页面 current_page.content = page4 page.update() def histroy_search(e): histroy_data_table.rows = [] start_time = None end_time = None if start_date.text != '请选择起始日期': start_time = start_date.text if end_date.text != '请选择结束日期': end_time = end_date.text print(start_time, end_time) full_start_time = f"{start_time} 00:00:00" full_end_time = f"{end_time} 23:59:59" batches = battery_db.get_batches_by_time_range_with_daily_sort(full_start_time, full_end_time) print('batches',batches) for index, item in enumerate(batches): # 为每条记录创建查看详情按钮 view_button = ft.ElevatedButton( "查看详情", icon=ft.Icons.VISIBILITY, width=100, height=30, style=ft.ButtonStyle( color=ft.Colors.WHITE, bgcolor=ft.Colors.BLUE_600, padding=ft.Padding(5, 5, 5, 5), ), on_click=lambda e, record=item['id']: view_details(e, record) ) histroy_data_table.rows.append( ft.DataRow([ ft.DataCell(ft.Text( str(index + 1), color=ft.Colors.WHITE, width=50, size=12, # 减小字体大小 no_wrap=False # 允许自动换行 )), ft.DataCell(ft.Text( item['created_time'], color=ft.Colors.WHITE, width=200, size=12, no_wrap=False )), ft.DataCell(view_button) # 添加查看详情按钮 ]) ) histroy_data_table.update() def handle_change_start(e): page.add(ft.Text(f"Date changed: {e.control.value.strftime('%Y-%m-%d')}")) start_date.text = e.control.value.strftime('%Y-%m-%d') start_date.update() def handle_change_end(e): page.add(ft.Text(f"Date changed: {e.control.value.strftime('%Y-%m-%d')}")) end_date.text = e.control.value.strftime('%Y-%m-%d') end_date.update() def handle_dismissal(e): page.add(ft.Text(f"DatePicker dismissed")) # 历史数据页面 page3 = ft.SafeArea( ft.Column([ # 上方输入框区域,带白色边框和外边距 ft.Container( content=ft.Column([ ft.Row([ ft.Row([ ft.Text("起始日期:", color=ft.Colors.WHITE, size=14, width=80, ), start_date ]), ft.Row([ ft.Text("结束日期:", color=ft.Colors.WHITE, size=14, width=80, ), end_date ]), ft.ElevatedButton("查询", icon=ft.Colors.WHITE, width=150, on_click=histroy_search) ]), ], spacing=15), padding=20, margin=ft.Margin(20, 20, 20, 10), border=ft.border.all(0.5, ft.Colors.WHITE), bgcolor=ft.Colors.BLACK26, ), # 下方表格区域 ft.Container( content=ft.ListView( width=1000, height=400, spacing=0, controls=[ ft.Row( scroll=ft.ScrollMode.ALWAYS, controls=[ histroy_data_table ] ) ] ), padding=20, margin=ft.Margin(20, 10, 20, 20), border=ft.border.all(0.5, ft.Colors.WHITE), bgcolor=ft.Colors.BLACK26, ) ]) ) DetectionType = ['低压损'] # 1到70 DetectionType.extend([int(i) for i in range(1, 71)]) # 添加最后一个元素 def get_options(): options = [] for i in DetectionType: # 确保键是字符串类型 key = str(i) options.append( ft.DropdownOption( key=key, content=ft.Text( value=key, color=ft.Colors.WHITE, ), ) ) return options def histroy_search_list(e): print(e) s.batch_id = e histroy_data_item = ft.DataTable( width=900, # 表格最小宽度,确保列不挤压 columns=[ ft.DataColumn(ft.Text("序号", color=ft.Colors.WHITE, width=50, size=12, no_wrap=False)), ft.DataColumn(ft.Text("上面二维码", color=ft.Colors.WHITE, width=150, size=12, no_wrap=False)), ft.DataColumn(ft.Text("下面二维码", color=ft.Colors.WHITE, width=150, size=12, no_wrap=False)), ft.DataColumn(ft.Text("H2", color=ft.Colors.WHITE, width=50, size=12, no_wrap=False)), ft.DataColumn(ft.Text("O2", color=ft.Colors.WHITE, width=50, size=12, no_wrap=False)), ft.DataColumn(ft.Text("厚度", color=ft.Colors.WHITE, width=50, size=12, no_wrap=False)), ], rows=[ ft.DataRow(cells=[ ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=50)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=150)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=150)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=50)), ft.DataCell(ft.Text(" ", color=ft.Colors.WHITE, width=50)), ft.DataCell(ft.Text(" ", color=ft.Colors.GREEN, width=50)), ]), ], ) def dropdown_changed(e=None, group_id=None): """下拉列表选择变化事件处理 Args: e: 事件对象(可选) group_id: 直接指定的组ID(可选) """ # 确定选择的组ID selected_group = None if group_id is not None: # 如果直接指定了group_id selected_group = group_id print(f"通过group_id参数传入: {selected_group}, 类型: {type(selected_group)}") elif e is not None and hasattr(e, 'control') and hasattr(e.control, 'value'): # 如果是通过下拉列表事件触发 selected_group = e.control.value print(f"通过下拉列表事件传入: {selected_group}, 类型: {type(selected_group)}") elif e is not None and isinstance(e, dict) and 'data' in e: # 如果是通过字典事件触发 selected_group = e['data'] print(f"通过字典事件传入: {selected_group}, 类型: {type(selected_group)}") elif e is not None and hasattr(e, 'data'): # 如果是其他类型的事件对象 selected_group = e.data print(f"通过其他事件传入: {selected_group}, 类型: {type(selected_group)}") if selected_group is None: print("没有选择有效的组") return print(f"最终选择的组: {selected_group}, 类型: {type(selected_group)}") histroy_data_item.rows = [] # 处理组ID(如果是'低压损'则转换为71) actual_group_id = 71 if selected_group == '低压损' else selected_group print(f"实际查询的组ID: {actual_group_id}, 类型: {type(actual_group_id)}") # 获取组数据 group_item = battery_db.get_batch_data(int(s.batch_id), actual_group_id) for index, item in enumerate(group_item): histroy_data_item.rows.append( ft.DataRow([ ft.DataCell(ft.Text( str(index + 1), color=ft.Colors.WHITE, width=50, size=12, no_wrap=False )), ft.DataCell(ft.Text( item.get('top_qr_code'), color=ft.Colors.WHITE, width=150, size=12, no_wrap=False )), ft.DataCell(ft.Text( item.get('bottom_qr_code'), color=ft.Colors.WHITE, width=150, size=12, no_wrap=False )), ft.DataCell(ft.Text( str(item.get('h2_value')), color=ft.Colors.WHITE, width=50, size=12, no_wrap=False )), ft.DataCell(ft.Text( str(item.get('o2_value')), color=ft.Colors.WHITE, width=50, size=12, no_wrap=False )), ft.DataCell(ft.Text( str(item.get('thickness')), color=ft.Colors.WHITE, width=50, size=12, no_wrap=False )), ]) ) histroy_data_item.update() print(f"加载了 {len(group_item)} 条数据") # 在搜索函数中 dd.value = actual_group_id dd.update() dd = ft.Dropdown( editable=True, label="组次", options=get_options(), on_change=dropdown_changed, bgcolor=ft.Colors.BLUE, hint_style=ft.TextStyle(color=ft.Colors.WHITE, italic=True), text_style=ft.TextStyle( color=ft.Colors.WHITE, weight=ft.FontWeight.BOLD, size=14, ), ) # 返回历史数据页面的函数 def back_to_history(e): dd.value = None dd.update() histroy_data_item.rows = [] current_page.content = page3 page.update() # 创建输入框控件(在适当的位置定义) top_qr_input = ft.TextField( width=200, height=35, text_size=16, hint_text="上面二维码", color=ft.Colors.WHITE, content_padding=ft.Padding(5, 5, 5, 5), ) bottom_qr_input = ft.TextField( width=200, height=35, text_size=16, hint_text="下面二维码", color=ft.Colors.WHITE, content_padding=ft.Padding(5, 5, 5, 5), ) # 搜索函数 def search_by_qr_code(e): top_qr = top_qr_input.value bottom_qr = bottom_qr_input.value if not top_qr and not bottom_qr: # 如果没有输入任何二维码,显示提示 page.snack_bar = ft.SnackBar(content=ft.Text("请输入上面二维码或下面二维码")) page.snack_bar.open = True page.update() return # 调用数据库方法查找对应的组 matched_groups = battery_db.get_group_by_qr_codes_exact(s.batch_id, top_qr, bottom_qr) if matched_groups: # 如果找到匹配的组,跳转到第一个匹配的组 first_group = matched_groups[0]['group_id'] print(f"找到的组ID: {first_group}, 类型: {type(first_group)}") # 调试信息 # 设置下拉列表的值(确保转换为字符串) # 直接调用 dropdown_changed 函数,传入组ID(不传事件对象) dropdown_changed(group_id=first_group) # 显示成功消息 if len(matched_groups) > 1: page.snack_bar = ft.SnackBar( content=ft.Text(f"找到 {len(matched_groups)} 个匹配的组,已跳转到组 {first_group}") ) else: page.snack_bar = ft.SnackBar( content=ft.Text(f"已跳转到组 {first_group}") ) page.snack_bar.open = True page.update() else: # 没有找到匹配的组 page.snack_bar = ft.SnackBar( content=ft.Text("未找到匹配的组,请检查二维码是否正确") ) page.snack_bar.open = True page.update() # 详情页面 (page4) # 修改 page4 中的表格容器 page4 = ft.SafeArea( ft.Column([ ft.Container( content=ft.Row([ ft.ElevatedButton( "返回", icon=ft.Icons.ARROW_BACK, on_click=back_to_history, style=ft.ButtonStyle( color=ft.Colors.WHITE, bgcolor=ft.Colors.BLUE_600, ) ), dd, # 在同一行添加搜索区域 ft.Text("上面二维码:", color=ft.Colors.WHITE, size=16), top_qr_input, ft.Text("下面二维码:", color=ft.Colors.WHITE, size=16), bottom_qr_input, ft.ElevatedButton( "搜索", icon=ft.Icons.SEARCH, width=80, on_click=search_by_qr_code ) ], alignment=ft.MainAxisAlignment.START, spacing=10), padding=20, margin=ft.Margin(20, 20, 20, 10), border=ft.border.all(0.5, ft.Colors.WHITE), bgcolor=ft.Colors.BLACK26, ), ft.Container( content=ft.ListView( # 使用 ListView 包装表格 width=1000, height=430, spacing=0, controls=[ ft.Row( scroll=ft.ScrollMode.ALWAYS, controls=[ histroy_data_item ] ) ] ), padding=20, margin=ft.Margin(20, 0, 20, 20), border=ft.border.all(0.5, ft.Colors.WHITE), bgcolor=ft.Colors.BLACK26, ) ]) ) pages = [page0, page1, page3, page4] # 添加page4到页面列表 current_page = ft.Container(content=pages[0]) def on_nav_change(e): if e.control.selected_index < 3: # 只有前三个页面可以通过导航栏访问 current_page.content = pages[e.control.selected_index] page.update() # 导航栏 page.navigation_bar = ft.CupertinoNavigationBar( bgcolor=ft.Colors.BLUE_50, inactive_color=ft.Colors.BLUE_GREY_600, active_color=ft.Colors.BLUE_800, on_change=on_nav_change, destinations=[ ft.NavigationBarDestination( icon=ft.Icons.MONITOR_OUTLINED, selected_icon=ft.Icons.MONITOR, label="上料" ), ft.NavigationBarDestination( icon=ft.Icons.MONITOR_OUTLINED, selected_icon=ft.Icons.MONITOR, label="实时监控" ), ft.NavigationBarDestination( icon=ft.Icons.HISTORY_OUTLINED, selected_icon=ft.Icons.HISTORY, label="历史数据" ), ], ) background_layout = ft.Stack([ ft.Image( src="1.jpg", fit=ft.ImageFit.COVER, width=1024, height=768, ), ft.Container( bgcolor=ft.Colors.BLACK12, width=page.width, height=page.height, ), current_page ]) page.add(background_layout) s.page_initialized = True # 页面构建完成,设置初始化标志 # 确保这是唯一的 ft.app 调用 if __name__ == "__main__": ft.app(main)