import streamlit as st import plotly.express as px import plotly.graph_objects as go import pandas as pd from datetime import datetime, timedelta from app.services.extruder_service import ExtruderService from app.services.main_process_service import MainProcessService def show_metered_weight_dashboard(): # 初始化服务 extruder_service = ExtruderService() main_process_service = MainProcessService() # 页面标题 st.title("米重综合分析") # 初始化会话状态用于日期同步 if 'mw_start_date' not in st.session_state: st.session_state['mw_start_date'] = datetime.now().date() - timedelta(days=7) if 'mw_end_date' not in st.session_state: st.session_state['mw_end_date'] = datetime.now().date() if 'mw_quick_select' not in st.session_state: st.session_state['mw_quick_select'] = "最近7天" # 定义回调函数 def update_dates(qs): st.session_state['mw_quick_select'] = qs today = datetime.now().date() if qs == "今天": st.session_state['mw_start_date'] = today st.session_state['mw_end_date'] = today elif qs == "最近3天": st.session_state['mw_start_date'] = today - timedelta(days=3) st.session_state['mw_end_date'] = today elif qs == "最近7天": st.session_state['mw_start_date'] = today - timedelta(days=7) st.session_state['mw_end_date'] = today elif qs == "最近30天": st.session_state['mw_start_date'] = today - timedelta(days=30) st.session_state['mw_end_date'] = today def on_date_change(): st.session_state['mw_quick_select'] = "自定义" # 查询条件区域 with st.expander("🔍 查询配置", expanded=True): # 添加自定义 CSS 实现响应式换行 st.markdown(""" """, unsafe_allow_html=True) # 创建布局 cols = st.columns([1, 1, 1, 1, 1, 1.5, 1.5, 1]) options = ["今天", "最近3天", "最近7天", "最近30天", "自定义"] for i, option in enumerate(options): with cols[i]: # 根据当前选择状态决定按钮类型 button_type = "primary" if st.session_state['mw_quick_select'] == option else "secondary" if st.button(option, key=f"btn_mw_{option}", width='stretch', type=button_type): update_dates(option) st.rerun() with cols[5]: start_date = st.date_input( "开始日期", label_visibility="collapsed", key="mw_start_date", on_change=on_date_change ) with cols[6]: end_date = st.date_input( "结束日期", label_visibility="collapsed", key="mw_end_date", on_change=on_date_change ) with cols[7]: query_button = st.button("🚀 开始分析", key="mw_query", width='stretch') # 转换为datetime对象 start_dt = datetime.combine(start_date, datetime.min.time()) end_dt = datetime.combine(end_date, datetime.max.time()) # 查询处理 if query_button: with st.spinner("正在聚合数据..."): # 1. 获取挤出机数据 df_extruder = extruder_service.get_extruder_data(start_dt, end_dt) # 处理机头压力,去除超过2的值 if df_extruder is not None and not df_extruder.empty: df_extruder = df_extruder[df_extruder['head_pressure'] <= 2] # 2. 获取主流程控制数据 df_main_speed = main_process_service.get_cutting_setting_data(start_dt, end_dt) df_temp = main_process_service.get_temperature_control_data(start_dt, end_dt) # 获取电机运行监视数据 df_motor = main_process_service.get_motor_monitoring_data(start_dt, end_dt) # 处理电机线速数据,除以10 if df_motor is not None and not df_motor.empty: df_motor['m1_line_speed'] = df_motor['m1_line_speed'] / 10 df_motor['m2_line_speed'] = df_motor['m2_line_speed'] / 10 # 检查是否有数据 has_data = any([ df_extruder is not None and not df_extruder.empty, df_main_speed is not None and not df_main_speed.empty, df_temp is not None and not df_temp.empty, df_motor is not None and not df_motor.empty ]) if not has_data: st.warning("所选时间段内未找到任何数据,请尝试调整查询条件。") return # --- 图表1: 米重与实际参数分析 --- st.subheader("📈 米重与实际参数分析") fig1 = go.Figure() # 添加米重 if df_extruder is not None and not df_extruder.empty: fig1.add_trace(go.Scatter( x=df_extruder['time'], y=df_extruder['metered_weight'], name='米重 (Kg/m)', mode='lines', line=dict(color='blue', width=2), yaxis='y1' )) # 添加挤出机实际转速 fig1.add_trace(go.Scatter( x=df_extruder['time'], y=df_extruder['screw_speed_actual'], name='挤出机实际转速 (RPM)', mode='lines', line=dict(color='green', width=1.5), yaxis='y2' )) # 添加挤出机机头压力 fig1.add_trace(go.Scatter( x=df_extruder['time'], y=df_extruder['head_pressure'], name='挤出机机头压力', mode='lines', line=dict(color='orange', width=1.5), yaxis='y3' )) # 添加流程主速 if df_main_speed is not None and not df_main_speed.empty: fig1.add_trace(go.Scatter( x=df_main_speed['time'], y=df_main_speed['process_main_speed'], name='流程主速 (M/Min)', mode='lines', line=dict(color='red', width=1.5), yaxis='y4' # 单独的速度轴 )) # 添加温度显示值 if df_temp is not None and not df_temp.empty: temp_display_fields = { 'nakata_extruder_screw_display_temp': '螺杆显示 (°C)', 'nakata_extruder_rear_barrel_display_temp': '后机筒显示 (°C)', 'nakata_extruder_front_barrel_display_temp': '前机筒显示 (°C)', 'nakata_extruder_head_display_temp': '机头显示 (°C)', } for field, label in temp_display_fields.items(): fig1.add_trace(go.Scatter( x=df_temp['time'], y=df_temp[field], name=label, mode='lines', line=dict(width=1), yaxis='y5' )) # 添加电机线速数据 if df_motor is not None and not df_motor.empty: fig1.add_trace(go.Scatter( x=df_motor['time'], y=df_motor['m1_line_speed'], name='拉出一段线速 (M/Min)', mode='lines', line=dict(color='cyan', width=1.5), yaxis='y4' )) fig1.add_trace(go.Scatter( x=df_motor['time'], y=df_motor['m2_line_speed'], name='拉出二段线速 (M/Min)', mode='lines', line=dict(color='teal', width=1.5), yaxis='y4' )) # 设置图表1布局 fig1.update_layout( title='米重与实际参数趋势分析', xaxis=dict( title='时间', rangeslider=dict(visible=True), type='date' ), yaxis=dict( title='米重 (Kg/m)', title_font=dict(color='blue'), tickfont=dict(color='blue') ), yaxis2=dict( title='挤出机转速 (RPM)', title_font=dict(color='green'), tickfont=dict(color='green'), overlaying='y', side='right' ), yaxis3=dict( title='机头压力', title_font=dict(color='orange'), tickfont=dict(color='orange'), overlaying='y', side='right', anchor='free', position=0.85 ), yaxis4=dict( title='流程主速 (M/Min)', title_font=dict(color='red'), tickfont=dict(color='red'), overlaying='y', side='right', anchor='free', position=0.75 ), yaxis5=dict( title='温度显示 (°C)', title_font=dict(color='purple'), tickfont=dict(color='purple'), overlaying='y', side='left', anchor='free', position=0.15 ), yaxis6=dict( title='拉出线速 (M/Min)', title_font=dict(color='cyan'), tickfont=dict(color='cyan'), overlaying='y', side='right', anchor='free', position=0.65 ), legend=dict( orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1 ), height=600, margin=dict(l=100, r=200, t=100, b=100), hovermode='x unified' ) # 显示图表1 st.plotly_chart(fig1, width='stretch', config={'scrollZoom': True}) # --- 图表2: 米重与设定参数分析 --- st.subheader("📈 米重与设定参数分析") fig2 = go.Figure() # 添加米重 if df_extruder is not None and not df_extruder.empty: fig2.add_trace(go.Scatter( x=df_extruder['time'], y=df_extruder['metered_weight'], name='米重 (Kg/m)', mode='lines', line=dict(color='blue', width=2), yaxis='y1' )) # 添加挤出机设定转速 fig2.add_trace(go.Scatter( x=df_extruder['time'], y=df_extruder['screw_speed_set'], name='挤出机设定转速 (RPM)', mode='lines', line=dict(color='green', width=1.5, dash='dash'), yaxis='y2' )) # 添加挤出机机头压力 fig2.add_trace(go.Scatter( x=df_extruder['time'], y=df_extruder['head_pressure'], name='挤出机机头压力', mode='lines', line=dict(color='orange', width=1.5), yaxis='y3' )) # 添加流程主速 if df_main_speed is not None and not df_main_speed.empty: fig2.add_trace(go.Scatter( x=df_main_speed['time'], y=df_main_speed['process_main_speed'], name='流程主速 (M/Min)', mode='lines', line=dict(color='red', width=1.5), yaxis='y4' # 单独的速度轴 )) # 添加温度设定值 if df_temp is not None and not df_temp.empty: temp_set_fields = { 'nakata_extruder_screw_set_temp': '螺杆设定 (°C)', 'nakata_extruder_rear_barrel_set_temp': '后机筒设定 (°C)', 'nakata_extruder_front_barrel_set_temp': '前机筒设定 (°C)', 'nakata_extruder_head_set_temp': '机头设定 (°C)', } for field, label in temp_set_fields.items(): fig2.add_trace(go.Scatter( x=df_temp['time'], y=df_temp[field], name=label, mode='lines', line=dict(width=1, dash='dash'), yaxis='y5' )) # 设置图表2布局 fig2.update_layout( title='米重与设定参数趋势分析', xaxis=dict( title='时间', rangeslider=dict(visible=True), type='date' ), yaxis=dict( title='米重 (Kg/m)', title_font=dict(color='blue'), tickfont=dict(color='blue') ), yaxis2=dict( title='挤出机转速 (RPM)', title_font=dict(color='green'), tickfont=dict(color='green'), overlaying='y', side='right' ), yaxis3=dict( title='机头压力', title_font=dict(color='orange'), tickfont=dict(color='orange'), overlaying='y', side='right', anchor='free', position=0.85 ), yaxis4=dict( title='流程主速 (M/Min)', title_font=dict(color='red'), tickfont=dict(color='red'), overlaying='y', side='right', anchor='free', position=0.75 ), yaxis5=dict( title='温度设定 (°C)', title_font=dict(color='purple'), tickfont=dict(color='purple'), overlaying='y', side='left', anchor='free', position=0.15 ), legend=dict( orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1 ), height=600, margin=dict(l=100, r=150, t=100, b=100), hovermode='x unified' ) # 显示图表2 st.plotly_chart(fig2, width='stretch', config={'scrollZoom': True}) # 数据摘要 # st.subheader("📊 数据摘要") # summary_cols = st.columns(4) # with summary_cols[0]: # if df_extruder is not None and not df_extruder.empty: # st.metric("平均米重", f"{df_extruder['metered_weight'].mean():.2f} Kg/m") # with summary_cols[1]: # if df_extruder is not None and not df_extruder.empty: # st.metric("平均设定转速", f"{df_extruder['screw_speed_set'].mean():.2f} RPM") # with summary_cols[2]: # if df_extruder is not None and not df_extruder.empty: # st.metric("平均实际转速", f"{df_extruder['screw_speed_actual'].mean():.2f} RPM") # with summary_cols[3]: # if df_extruder is not None and not df_extruder.empty: # st.metric("平均机头压力", f"{df_extruder['head_pressure'].mean():.2f}")