import streamlit as st import plotly.express as px import plotly.graph_objects as go from datetime import datetime, timedelta from app.services.extruder_service import ExtruderService from app.services.data_processing_service import DataProcessingService # 初始化服务 extruder_service = ExtruderService() processing_service = DataProcessingService() def run_extruder_dashboard(): # 页面标题 st.title("挤出机数据分析仪表盘") # 侧边栏:日期范围选择 st.sidebar.header("查询配置") start_date = st.sidebar.date_input("开始日期", datetime.now() - timedelta(days=7)) end_date = st.sidebar.date_input("结束日期", datetime.now()) # 转换为datetime对象(包含时间) start_datetime = datetime.combine(start_date, datetime.min.time()) end_datetime = datetime.combine(end_date, datetime.max.time()) # 查询按钮 if st.sidebar.button("查询数据"): # 验证日期范围 if start_datetime > end_datetime: st.error("开始日期不能晚于结束日期!") else: # 显示加载状态 with st.spinner("正在查询数据..."): # 查询数据 raw_data = extruder_service.get_extruder_data(start_datetime, end_datetime) if raw_data is None or raw_data.empty: st.warning("未查询到数据,请检查日期范围或数据库连接!") else: # 清洗数据 cleaned_data = processing_service.clean_data(raw_data) # 检测换批事件 batch_changes = extruder_service.detect_batch_changes(cleaned_data) # 分析参数趋势 trends = extruder_service.analyze_parameter_trends(cleaned_data) # 检测异常 anomalies = extruder_service.detect_anomalies(cleaned_data) # 显示数据概览 st.subheader("数据概览") col1, col2, col3, col4 = st.columns(4) with col1: st.metric("总记录数", len(cleaned_data)) with col2: st.metric("换批次数", len(batch_changes)) with col3: st.metric("数据时间范围", f"{cleaned_data['time'].min()} 至 {cleaned_data['time'].max()}") with col4: st.metric("异常数量", len(anomalies)) # 显示换批分析 st.subheader("换批分析") if not batch_changes.empty: # 准备展示数据 batch_display = batch_changes[['spec_name', 'start_time', 'end_time', 'duration_minutes', 'production_kg']].copy() batch_display.columns = ['SPEC编号', '开始时间', '结束时间', '持续时长(分钟)', '生产数量(kg)'] # 格式化时间 batch_display['开始时间'] = batch_display['开始时间'].dt.strftime('%Y-%m-%d %H:%M:%S') batch_display['结束时间'] = batch_display['结束时间'].dt.strftime('%Y-%m-%d %H:%M:%S') # 显示数据表格 st.dataframe(batch_display, use_container_width=True) else: st.warning("未检测到换批事件") # 显示参数趋势图 st.subheader("参数趋势图") # 螺杆转速趋势 st.subheader("螺杆转速趋势") fig1 = px.line( cleaned_data, x='time', y=['screw_speed_set', 'screw_speed_actual'], labels={ 'time': '时间', 'value': '转速(rpm)', 'variable': '参数' }, title='螺杆转速趋势', color_discrete_map={ 'screw_speed_set': 'blue', 'screw_speed_actual': 'green' } ) fig1.for_each_trace(lambda t: t.update(name={ 'screw_speed_set': '设定转速', 'screw_speed_actual': '实际转速' }[t.name])) st.plotly_chart(fig1, use_container_width=True) # 挤出机电流趋势 st.subheader("挤出机电流趋势") fig2 = px.line( cleaned_data, x='time', y='extruder_current', labels={ 'time': '时间', 'extruder_current': '电流(A)' }, title='挤出机电流趋势' ) st.plotly_chart(fig2, use_container_width=True) # 机头压力趋势 st.subheader("机头压力趋势") fig3 = px.line( cleaned_data, x='time', y='head_pressure', labels={ 'time': '时间', 'head_pressure': '压力(MPa)' }, title='机头压力趋势' ) st.plotly_chart(fig3, use_container_width=True) # 米称重量趋势 st.subheader("米称重量趋势") fig4 = px.line( cleaned_data, x='time', y='metered_weight', labels={ 'time': '时间', 'metered_weight': '重量(kg)' }, title='米称重量趋势' ) st.plotly_chart(fig4, use_container_width=True) # 显示原始数据 st.subheader("原始数据") st.dataframe(cleaned_data, use_container_width=True) # 关闭数据库连接 def on_app_close(): extruder_service.close_connection() # 注册应用关闭回调 st.session_state['app_close'] = on_app_close