From faa25a85c10aa0fa2df824318a4bfa542f6a5a46 Mon Sep 17 00:00:00 2001
From: baoshiwei <baoshiwei@shlanbao.cn>
Date: 星期二, 20 一月 2026 13:26:55 +0800
Subject: [PATCH] feat(services): 添加主流程服务并重构时间处理逻辑

---
 /dev/null                               |  161 ----
 app/pages/extruder_dashboard.py         |  344 ++++++++
 app/pages/comprehensive_dashboard.py    |  329 ++++++++
 app/pages/sorting_dashboard.py          |  416 ++++++++++
 app/services/extruder_service.py        |   23 
 app/pages/main_process_dashboard.py     |  172 ++++
 app/services/data_query_service.py      |   20 
 dashboard.py                            |  758 +-----------------
 app/services/main_process_service.py    |   88 ++
 app/services/data_processing_service.py |   47 
 10 files changed, 1,436 insertions(+), 922 deletions(-)

diff --git a/app/dashboard/extruder_dashboard.py b/app/dashboard/extruder_dashboard.py
deleted file mode 100644
index 3ea6da8..0000000
--- a/app/dashboard/extruder_dashboard.py
+++ /dev/null
@@ -1,161 +0,0 @@
-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())
-
-    # 杞崲涓篸atetime瀵硅薄锛堝寘鍚椂闂达級
-    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("姝e湪鏌ヨ鏁版嵁..."):
-                # 鏌ヨ鏁版嵁
-                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
\ No newline at end of file
diff --git a/app/pages/comprehensive_dashboard.py b/app/pages/comprehensive_dashboard.py
new file mode 100644
index 0000000..3f1097e
--- /dev/null
+++ b/app/pages/comprehensive_dashboard.py
@@ -0,0 +1,329 @@
+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.data_query_service import DataQueryService
+from app.services.extruder_service import ExtruderService
+from app.services.main_process_service import MainProcessService
+
+def show_comprehensive_dashboard():
+    # 鍒濆鍖栨湇鍔�
+    sorting_service = DataQueryService()
+    extruder_service = ExtruderService()
+    main_process_service = MainProcessService()
+
+    # 椤甸潰鏍囬
+    st.title("澶氱淮缁煎悎鍒嗘瀽")
+
+    # 鍒濆鍖栦細璇濈姸鎬佺敤浜庢棩鏈熷悓姝�
+    if 'comp_start_date' not in st.session_state:
+        st.session_state['comp_start_date'] = datetime.now().date() - timedelta(days=7)
+    if 'comp_end_date' not in st.session_state:
+        st.session_state['comp_end_date'] = datetime.now().date()
+    if 'comp_quick_select' not in st.session_state:
+        st.session_state['comp_quick_select'] = "鏈�杩�7澶�"
+
+    # 瀹氫箟鍥炶皟鍑芥暟
+    def update_dates(qs):
+        st.session_state['comp_quick_select'] = qs
+        today = datetime.now().date()
+        if qs == "浠婂ぉ":
+            st.session_state['comp_start_date'] = today
+            st.session_state['comp_end_date'] = today
+        elif qs == "鏈�杩�3澶�":
+            st.session_state['comp_start_date'] = today - timedelta(days=3)
+            st.session_state['comp_end_date'] = today
+        elif qs == "鏈�杩�7澶�":
+            st.session_state['comp_start_date'] = today - timedelta(days=7)
+            st.session_state['comp_end_date'] = today
+        elif qs == "鏈�杩�30澶�":
+            st.session_state['comp_start_date'] = today - timedelta(days=30)
+            st.session_state['comp_end_date'] = today
+
+    def on_date_change():
+        st.session_state['comp_quick_select'] = "鑷畾涔�"
+
+    # 鏌ヨ鏉′欢鍖哄煙
+    with st.expander("馃攳 鏌ヨ閰嶇疆", expanded=True):
+        # 娣诲姞鑷畾涔� CSS 瀹炵幇鍝嶅簲寮忔崲琛�
+        st.markdown("""
+            <style>
+            /* 寮哄埗鍒楀鍣ㄦ崲琛� */
+            [data-testid="stExpander"] [data-testid="column"] {
+                flex: 1 1 120px !important;
+                min-width: 120px !important;
+            }
+            /* 閽堝鏃ユ湡杈撳叆妗嗗垪绋嶅井鍔犲涓�鐐� */
+            @media (min-width: 768px) {
+                [data-testid="stExpander"] [data-testid="column"]:nth-child(6),
+                [data-testid="stExpander"] [data-testid="column"]:nth-child(7) {
+                    flex: 2 1 180px !important;
+                    min-width: 180px !important;
+                }
+            }
+            </style>
+            """, 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['comp_quick_select'] == option else "secondary"
+                if st.button(option, key=f"btn_comp_{option}", width='stretch', type=button_type):
+                    update_dates(option)
+                    st.rerun()
+
+        with cols[5]:
+            start_date = st.date_input(
+                "寮�濮嬫棩鏈�", 
+                label_visibility="collapsed",
+                key="comp_start_date",
+                on_change=on_date_change
+            )
+        
+        with cols[6]:
+            end_date = st.date_input(
+                "缁撴潫鏃ユ湡", 
+                label_visibility="collapsed",
+                key="comp_end_date",
+                on_change=on_date_change
+            )
+
+        with cols[7]:
+            query_button = st.button("馃殌 鏌ヨ", key="comp_query", width='stretch')
+
+    # 杞崲涓篸atetime瀵硅薄
+    start_dt = datetime.combine(start_date, datetime.min.time())
+    end_dt = datetime.combine(end_date, datetime.max.time())
+
+    # 鏌ヨ澶勭悊
+    if query_button:
+        with st.spinner("姝e湪鑱氬悎澶氭簮鏁版嵁..."):
+            # 1. 鑾峰彇鍒嗘嫞纾呯Г鏁版嵁
+            df_sorting = sorting_service.get_sorting_scale_data(start_dt, end_dt)
+            # 2. 鑾峰彇鎸ゅ嚭鏈烘暟鎹�
+            df_extruder = extruder_service.get_extruder_data(start_dt, end_dt)
+            # 3. 鑾峰彇涓绘祦绋嬫帶鍒舵暟鎹�
+            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)
+
+            # 妫�鏌ユ槸鍚︽湁鏁版嵁
+            has_data = any([
+                df_sorting is not None and not df_sorting.empty,
+                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
+            ])
+
+            if not has_data:
+                st.warning("鎵�閫夋椂闂存鍐呮湭鎵惧埌浠讳綍鏁版嵁锛岃灏濊瘯璋冩暣鏌ヨ鏉′欢銆�")
+                return
+
+            # 鍒涘缓缁煎悎鍒嗘瀽鍥捐〃
+            fig = go.Figure()
+
+            # 娣诲姞鍒嗘嫞纾呯Г閲嶉噺 (鍩哄浘)
+            if df_sorting is not None and not df_sorting.empty:
+                # 妫�鏌ユ槸鍚﹀寘鍚槇鍊肩浉鍏冲瓧娈�
+                has_thresholds = all(col in df_sorting.columns for col in ['over_difference', 'under_difference'])
+                
+                if has_thresholds:
+                    # 鍒嗙姝e父鍜屽紓甯告暟鎹偣
+                    # 澶嶅埗鏁版嵁浠ラ伩鍏嶄慨鏀瑰師濮嬫暟鎹紝骞跺鐞嗗彲鑳界殑闆跺��/绌哄��
+                    plot_df = df_sorting.copy()
+                    is_out_of_range = (plot_df['weight'] > plot_df['over_difference']) | (plot_df['weight'] < plot_df['under_difference'])
+                    
+                    normal_points = plot_df[~is_out_of_range]
+                    anomaly_points = plot_df[is_out_of_range]
+                    
+                    # 1.1 姝e父閲嶉噺浠ヨ摑鑹叉暟鎹偣鏄剧ず
+                    if not normal_points.empty:
+                        fig.add_trace(go.Scatter(
+                            x=normal_points['time'], 
+                            y=normal_points['weight'],
+                            name='鍒嗘嫞閲嶉噺 (姝e父)',
+                            mode='markers',
+                            marker=dict(size=5, color='blue', opacity=0.7)
+                        ))
+                    
+                    # 1.2 寮傚父閲嶉噺浠ョ孩鑹蹭笁瑙掓樉绀�
+                    if not anomaly_points.empty:
+                        fig.add_trace(go.Scatter(
+                            x=anomaly_points['time'], 
+                            y=anomaly_points['weight'],
+                            name='鍒嗘嫞閲嶉噺 (寮傚父)',
+                            mode='markers',
+                            marker=dict(
+                                size=7, 
+                                color='red', 
+                                symbol='triangle-up',
+                                line=dict(width=1, color='darkred')
+                            )
+                        ))
+                else:
+                    # 濡傛灉娌℃湁闃堝�硷紝鍒欏叏閮ㄦ樉绀轰负鏅�氳摑鑹茬偣
+                    fig.add_trace(go.Scatter(
+                        x=df_sorting['time'], 
+                        y=df_sorting['weight'],
+                        name='鍒嗘嫞閲嶉噺 (kg)',
+                        mode='markers',
+                        marker=dict(size=5, color='blue', opacity=0.7)
+                    ))
+                
+                # 2. 鏄剧ず涓婁笅闄愬拰鏍囧噯鍊肩殑鏇茬嚎
+                if 'baseline_value' in df_sorting.columns:
+                     fig.add_trace(go.Scatter(
+                         x=df_sorting['time'], 
+                         y=df_sorting['baseline_value'],
+                         name='鍩哄噯鍊�',
+                         mode='lines',
+                         line=dict(color='green', width=2),
+                         opacity=0.6
+                     ))
+                
+                if 'over_difference' in df_sorting.columns:
+                    fig.add_trace(go.Scatter(
+                        x=df_sorting['time'], 
+                        y=df_sorting['over_difference'],
+                        name='涓婇檺闃堝��',
+                        mode='lines',
+                        line=dict(color='red', width=1.5),
+                        opacity=0.5
+                    ))
+                    
+                if 'under_difference' in df_sorting.columns:
+                    fig.add_trace(go.Scatter(
+                        x=df_sorting['time'], 
+                        y=df_sorting['under_difference'],
+                        name='涓嬮檺闃堝��',
+                        mode='lines',
+                        line=dict(color='orange', width=1.5),
+                        opacity=0.5
+                    ))
+
+            # 娣诲姞鎸ゅ嚭鏈虹背閲�
+            if df_extruder is not None and not df_extruder.empty:
+                fig.add_trace(go.Scatter(
+                    x=df_extruder['time'], 
+                    y=df_extruder['metered_weight'],
+                    name='鎸ゅ嚭鏈虹背閲� (g/m)',
+                    mode='lines',
+                    line=dict(color='green', width=1.5),
+                    yaxis='y2'
+                ))
+                # 娣诲姞鎸ゅ嚭鏈哄疄闄呰浆閫�
+                fig.add_trace(go.Scatter(
+                    x=df_extruder['time'], 
+                    y=df_extruder['screw_speed_actual'],
+                    name='鎸ゅ嚭鏈哄疄闄呰浆閫� (RPM)',
+                    mode='lines',
+                    line=dict(color='orange', width=1.5),
+                    yaxis='y3'
+                ))
+
+            # 娣诲姞娴佺▼涓婚��
+            if df_main_speed is not None and not df_main_speed.empty:
+                fig.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='y3' # 鍏辩敤閫熷害杞�
+                ))
+
+            # 娣诲姞娓╁害璁惧畾鍊�
+            if df_temp is not None and not df_temp.empty:
+                temp_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)'
+                }
+                colors = ['#FF4B4B', '#FF8C00', '#FFD700', '#DA70D6']
+                for i, (field, label) in enumerate(temp_fields.items()):
+                    fig.add_trace(go.Scatter(
+                        x=df_temp['time'], 
+                        y=df_temp[field],
+                        name=label,
+                        mode='lines',
+                        line=dict(width=1),
+                        yaxis='y4'
+                    ))
+
+            # 璁剧疆澶氬潗鏍囪酱甯冨眬
+            fig.update_layout(
+                title='澶氱淮缁煎悎瓒嬪娍鍒嗘瀽',
+                xaxis=dict(
+                    title='鏃堕棿',
+                    rangeslider=dict(visible=True),
+                    type='date'
+                ),
+                yaxis=dict(
+                    title='閲嶉噺 (kg)',
+                    title_font=dict(color='blue'),
+                    tickfont=dict(color='blue')
+                ),
+                yaxis2=dict(
+                    title='绫抽噸 (g/m)',
+                    title_font=dict(color='green'),
+                    tickfont=dict(color='green'),
+                    overlaying='y',
+                    side='right'
+                ),
+                yaxis3=dict(
+                    title='閫熷害 (RPM / M/Min)',
+                    title_font=dict(color='red'),
+                    tickfont=dict(color='red'),
+                    overlaying='y',
+                    side='right',
+                    anchor='free',
+                    position=0.85
+                ),
+                yaxis4=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=700,
+                margin=dict(l=100, r=100, t=100, b=100),
+                hovermode='x unified'
+            )
+
+            # 鏄剧ず鍥捐〃
+            st.plotly_chart(fig, width='stretch', config={'scrollZoom': True})
+            
+            # 鏁版嵁鎽樿
+            st.subheader("馃搳 鏁版嵁鎽樿")
+            summary_cols = st.columns(4)
+            
+            with summary_cols[0]:
+                if df_sorting is not None and not df_sorting.empty:
+                    st.metric("骞冲潎閲嶉噺", f"{df_sorting['weight'].mean():.2f} kg")
+            
+            with summary_cols[1]:
+                if df_extruder is not None and not df_extruder.empty:
+                    st.metric("骞冲潎绫抽噸", f"{df_extruder['metered_weight'].mean():.2f} g/m")
+            
+            with summary_cols[2]:
+                if df_main_speed is not None and not df_main_speed.empty:
+                    st.metric("骞冲潎涓婚��", f"{df_main_speed['process_main_speed'].mean():.2f} M/Min")
+            
+            with summary_cols[3]:
+                if df_temp is not None and not df_temp.empty:
+                    st.metric("骞冲潎铻烘潌娓╂帶", f"{df_temp['nakata_extruder_screw_set_temp'].mean():.1f} 掳C")
diff --git a/app/pages/extruder_dashboard.py b/app/pages/extruder_dashboard.py
new file mode 100644
index 0000000..9bae36f
--- /dev/null
+++ b/app/pages/extruder_dashboard.py
@@ -0,0 +1,344 @@
+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.data_processing_service import DataProcessingService
+
+def show_extruder_dashboard():
+    # 鍒濆鍖栨湇鍔�
+    extruder_service = ExtruderService()
+    processing_service = DataProcessingService()
+
+    # 椤甸潰鏍囬
+    st.title("鎸ゅ嚭鏈烘暟鎹垎鏋�")
+
+    # 鍒濆鍖栦細璇濈姸鎬佺敤浜庢棩鏈熷悓姝�
+    if 'extruder_start_date' not in st.session_state:
+        st.session_state['extruder_start_date'] = datetime.now().date() - timedelta(days=7)
+    if 'extruder_end_date' not in st.session_state:
+        st.session_state['extruder_end_date'] = datetime.now().date()
+    if 'extruder_quick_select' not in st.session_state:
+        st.session_state['extruder_quick_select'] = "鏈�杩�7澶�"
+
+    # 瀹氫箟鍥炶皟鍑芥暟
+    def update_dates(qs):
+        st.session_state['extruder_quick_select'] = qs
+        today = datetime.now().date()
+        if qs == "浠婂ぉ":
+            st.session_state['extruder_start_date'] = today
+            st.session_state['extruder_end_date'] = today
+        elif qs == "鏈�杩�3澶�":
+            st.session_state['extruder_start_date'] = today - timedelta(days=3)
+            st.session_state['extruder_end_date'] = today
+        elif qs == "鏈�杩�7澶�":
+            st.session_state['extruder_start_date'] = today - timedelta(days=7)
+            st.session_state['extruder_end_date'] = today
+        elif qs == "鏈�杩�30澶�":
+            st.session_state['extruder_start_date'] = today - timedelta(days=30)
+            st.session_state['extruder_end_date'] = today
+
+    def on_date_change():
+        st.session_state['extruder_quick_select'] = "鑷畾涔�"
+
+    # 鏌ヨ鏉′欢鍖哄煙
+    with st.expander("馃攳 鏌ヨ閰嶇疆", expanded=True):
+        # 娣诲姞鑷畾涔� CSS 瀹炵幇鍝嶅簲寮忔崲琛�
+        st.markdown("""
+            <style>
+            /* 寮哄埗鍒楀鍣ㄦ崲琛� */
+            [data-testid="stExpander"] [data-testid="column"] {
+                flex: 1 1 120px !important;
+                min-width: 120px !important;
+            }
+            /* 閽堝鏃ユ湡杈撳叆妗嗗垪绋嶅井鍔犲涓�鐐� */
+            @media (min-width: 768px) {
+                [data-testid="stExpander"] [data-testid="column"]:nth-child(6),
+                [data-testid="stExpander"] [data-testid="column"]:nth-child(7) {
+                    flex: 2 1 180px !important;
+                    min-width: 180px !important;
+                }
+            }
+            </style>
+            """, 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['extruder_quick_select'] == option else "secondary"
+                if st.button(option, key=f"btn_extruder_{option}", width='stretch', type=button_type):
+                    update_dates(option)
+                    st.rerun()
+
+        with cols[5]:
+            start_date = st.date_input(
+                "寮�濮嬫棩鏈�", 
+                label_visibility="collapsed",
+                key="extruder_start_date",
+                on_change=on_date_change
+            )
+        
+        with cols[6]:
+            end_date = st.date_input(
+                "缁撴潫鏃ユ湡", 
+                label_visibility="collapsed",
+                key="extruder_end_date",
+                on_change=on_date_change
+            )
+
+        with cols[7]:
+            query_button = st.button("馃殌 鏌ヨ", key="extruder_query", width='stretch')
+
+    # 杞崲涓篸atetime瀵硅薄锛堝寘鍚椂闂达級
+    start_datetime = datetime.combine(start_date, datetime.min.time())
+    end_datetime = datetime.combine(end_date, datetime.max.time())
+
+    # 鏌ヨ鎸夐挳澶勭悊
+    if query_button:
+        # 楠岃瘉鏃ユ湡鑼冨洿
+        if start_datetime > end_datetime:
+            st.error("寮�濮嬫棩鏈熶笉鑳芥櫄浜庣粨鏉熸棩鏈燂紒")
+        else:
+            # 鏄剧ず鍔犺浇鐘舵��
+            with st.spinner("姝e湪鏌ヨ鏁版嵁..."):
+                # 鏌ヨ鏁版嵁
+                raw_data = extruder_service.get_extruder_data(start_datetime, end_datetime)
+                
+                if raw_data is None or raw_data.empty:
+                    st.warning("鏈煡璇㈠埌鏁版嵁锛岃妫�鏌ユ棩鏈熻寖鍥存垨鏁版嵁搴撹繛鎺ワ紒")
+                    st.session_state['extruder_results'] = None
+                else:
+                    # 娓呮礂鏁版嵁
+                    cleaned_data = processing_service.clean_data(raw_data)
+                    
+                    # 妫�娴嬫崲鎵逛簨浠�
+                    batch_changes = extruder_service.detect_batch_changes(cleaned_data)
+                    
+                    # 缂撳瓨缁撴灉
+                    st.session_state['extruder_results'] = {
+                        'cleaned_data': cleaned_data,
+                        'batch_changes': batch_changes,
+                    }
+                    
+                    # 鏄剧ず鏁版嵁姒傝
+                    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()}")
+                    
+                    # 鏄剧ず鎹㈡壒鍒嗘瀽
+                    st.subheader("鎹㈡壒鍒嗘瀽")
+                    if not batch_changes.empty:
+                        # 鍑嗗灞曠ず鏁版嵁
+                        batch_display = batch_changes[['batch_id', 'compound_code', 'start_time', 'end_time', 'duration_minutes']].copy()
+                        
+                        # 鏍煎紡鍖栨椂闂�
+                        batch_display['start_time'] = batch_display['start_time'].dt.strftime('%Y-%m-%d %H:%M:%S')
+                        batch_display['end_time'] = batch_display['end_time'].dt.strftime('%Y-%m-%d %H:%M:%S')
+                        
+                        # 淇敼鍒楀悕
+                        batch_display.columns = ['鎵瑰彿', '鑳舵枡鍙�', '寮�濮嬫椂闂�', '缁撴潫鏃堕棿', '鎸佺画鏃堕暱(鍒嗛挓)']                                
+                        # 鏄剧ず鏁版嵁琛ㄦ牸
+                        st.dataframe(batch_display, use_container_width=True)
+                    else:
+                        st.warning("鏈娴嬪埌鎹㈡壒浜嬩欢")
+                    
+                    # 鏄剧ず鎹㈡枡鎿嶄綔鍙鍖栧浘琛�
+                    st.subheader("鎹㈡枡鎿嶄綔鍙鍖�")
+                    if not batch_changes.empty:
+                        # 鍒涘缓鎹㈡枡鎿嶄綔鍙鍖栧浘琛�
+                        fig = go.Figure()
+                        
+                        # 娣诲姞鍏抽敭鍙傛暟瓒嬪娍绾�
+                        fig.add_trace(go.Scatter(
+                            x=cleaned_data['time'],
+                            y=cleaned_data['screw_speed_actual'],
+                            name='瀹為檯杞��',
+                            line=dict(color='blue', width=2),
+                            opacity=0.8
+                        ))
+                        
+                        fig.add_trace(go.Scatter(
+                            x=cleaned_data['time'],
+                            y=cleaned_data['head_pressure'],
+                            name='鏈哄ご鍘嬪姏',
+                            line=dict(color='red', width=2),
+                            opacity=0.8,
+                            yaxis='y2'
+                        ))
+                        
+                        fig.add_trace(go.Scatter(
+                            x=cleaned_data['time'],
+                            y=cleaned_data['extruder_current'],
+                            name='鎸ゅ嚭鏈虹數娴�',
+                            line=dict(color='green', width=2),
+                            opacity=0.8,
+                            yaxis='y3'
+                        ))
+                        
+                        fig.add_trace(go.Scatter(
+                            x=cleaned_data['time'],
+                            y=cleaned_data['metered_weight'],
+                            name='绫抽噸',
+                            line=dict(color='orange', width=2),
+                            opacity=0.8,
+                            yaxis='y4'
+                        ))
+                        
+                        # 娣诲姞鎹㈡枡浜嬩欢鏍囪
+                        for i, row in batch_changes.iterrows():
+                            # 娣诲姞鍨傜洿绾�
+                            fig.add_shape(
+                                type="line",
+                                x0=row['start_time'],
+                                y0=0,
+                                x1=row['start_time'],
+                                y1=1,
+                                yref="paper",
+                                line=dict(color="purple", width=2, dash="dash")
+                            )
+                            
+                            # 娣诲姞娉ㄩ噴
+                            fig.add_annotation(
+                                x=row['start_time'],
+                                y=1,
+                                yref='paper',
+                                text=f'鎹㈡枡: {row["compound_code"]}\n鎵瑰彿: {row["batch_id"]}',
+                                showarrow=True,
+                                arrowhead=1,
+                                ax=0,
+                                ay=-60
+                            )
+                        
+                        # 閰嶇疆鍥捐〃甯冨眬
+                        fig.update_layout(
+                            title='鎹㈡枡鎿嶄綔鍏抽敭鍙傛暟鍙樺寲瓒嬪娍',
+                            xaxis_title='鏃堕棿',
+                            xaxis=dict(
+                                rangeslider=dict(visible=True),
+                                type='date'
+                            ),
+                            yaxis_title='瀹為檯杞�� (rpm)',
+                            yaxis2=dict(
+                                title='鏈哄ご鍘嬪姏 (MPa)',
+                                overlaying='y',
+                                side='right',
+                                position=0.85
+                            ),
+                            yaxis3=dict(
+                                title='鎸ゅ嚭鏈虹數娴� (A)',
+                                overlaying='y',
+                                side='right',
+                                position=0.92
+                            ),
+                            yaxis4=dict(
+                                title='绫抽噸 (kg)',
+                                overlaying='y',
+                                side='right',
+                                position=1
+                            ),
+                            legend=dict(
+                                orientation="h",
+                                yanchor="bottom",
+                                y=1.02,
+                                xanchor="right",
+                                x=1
+                            ),
+                            hovermode='x unified',
+                            height=700
+                        )
+                        
+                        # 鏄剧ず鍥捐〃
+                        st.plotly_chart(fig, width='stretch', config={'scrollZoom': True})
+                        
+                        # 娣诲姞鏁版嵁瀵煎嚭鍔熻兘
+                        import io
+                        
+                        # 鍑嗗瀵煎嚭鏁版嵁
+                        export_data = []
+                        for i, row in batch_changes.iterrows():
+                            # 鑾峰彇鎹㈡枡鍓嶅悗鐨勬暟鎹�
+                            before_change = cleaned_data[cleaned_data['time'] < row['start_time']].tail(5)
+                            after_change = cleaned_data[cleaned_data['time'] >= row['start_time']].head(5)
+                            
+                            # 娣诲姞鎹㈡枡浜嬩欢璁板綍
+                            export_data.append({
+                                'event_type': '鎹㈡枡浜嬩欢',
+                                'batch_id': row['batch_id'],
+                                'compound_code': row['compound_code'],
+                                'time': row['start_time'],
+                                'screw_speed': '',
+                                'head_pressure': '',
+                                'extruder_current': '',
+                                'metered_weight': ''
+                            })
+                            
+                            # 娣诲姞鎹㈡枡鍓嶆暟鎹�
+                            for _, before_row in before_change.iterrows():
+                                export_data.append({
+                                    'event_type': '鎹㈡枡鍓�',
+                                    'batch_id': row['batch_id'],
+                                    'compound_code': row['compound_code'],
+                                    'time': before_row['time'],
+                                    'screw_speed': before_row['screw_speed_actual'],
+                                    'head_pressure': before_row['head_pressure'],
+                                    'extruder_current': before_row['extruder_current'],
+                                    'metered_weight': before_row['metered_weight']
+                                })
+                            
+                            # 娣诲姞鎹㈡枡鍚庢暟鎹�
+                            for _, after_row in after_change.iterrows():
+                                export_data.append({
+                                    'event_type': '鎹㈡枡鍚�',
+                                    'batch_id': row['batch_id'],
+                                    'compound_code': row['compound_code'],
+                                    'time': after_row['time'],
+                                    'screw_speed': after_row['screw_speed_actual'],
+                                    'head_pressure': after_row['head_pressure'],
+                                    'extruder_current': after_row['extruder_current'],
+                                    'metered_weight': after_row['metered_weight']
+                                })
+                        
+                        # 杞崲涓篋ataFrame
+                        export_df = pd.DataFrame(export_data)
+                        
+                        # 鍒涘缓CSV鏁版嵁
+                        csv_buffer = io.StringIO()
+                        export_df.to_csv(csv_buffer, index=False, encoding='utf-8-sig')
+                        csv_data = csv_buffer.getvalue()
+                        
+                        # 娣诲姞涓嬭浇鎸夐挳
+                        st.download_button(
+                            label="涓嬭浇鎹㈡枡鎿嶄綔鍒嗘瀽鏁版嵁",
+                            data=csv_data,
+                            file_name=f"鎹㈡枡鎿嶄綔鍒嗘瀽_{start_date}_{end_date}.csv",
+                            mime="text/csv"
+                        )
+                    else:
+                        st.warning("鏈娴嬪埌鎹㈡壒浜嬩欢锛屾棤娉曠敓鎴愭崲鏂欐搷浣滃浘琛�")
+                    
+                    # 鏄剧ず鍘熷鏁版嵁
+                    st.subheader("鍘熷鏁版嵁")
+                    st.dataframe(cleaned_data, use_container_width=True)
+
+    # 鏁版嵁搴撹繛鎺ョ姸鎬�
+    st.sidebar.subheader("鏁版嵁搴撶姸鎬�")
+    if extruder_service.db.is_connected():
+        st.sidebar.success("鏁版嵁搴撹繛鎺ユ甯�")
+    else:
+        st.sidebar.warning("鏁版嵁搴撴湭杩炴帴")
+
+if __name__ == "__main__":
+    show_extruder_dashboard()
diff --git a/app/pages/main_process_dashboard.py b/app/pages/main_process_dashboard.py
new file mode 100644
index 0000000..74fce54
--- /dev/null
+++ b/app/pages/main_process_dashboard.py
@@ -0,0 +1,172 @@
+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.main_process_service import MainProcessService
+
+def show_main_process_dashboard():
+    # 鍒濆鍖栨湇鍔�
+    service = MainProcessService()
+
+    # 椤甸潰鏍囬
+    st.title("涓绘祦绋嬫帶鍒舵暟鎹垎鏋�")
+
+    # 鍒濆鍖栦細璇濈姸鎬佺敤浜庢棩鏈熷悓姝�
+    if 'main_process_start_date' not in st.session_state:
+        st.session_state['main_process_start_date'] = datetime.now().date() - timedelta(days=7)
+    if 'main_process_end_date' not in st.session_state:
+        st.session_state['main_process_end_date'] = datetime.now().date()
+    if 'main_process_quick_select' not in st.session_state:
+        st.session_state['main_process_quick_select'] = "鏈�杩�7澶�"
+
+    # 瀹氫箟鍥炶皟鍑芥暟
+    def update_dates(qs):
+        st.session_state['main_process_quick_select'] = qs
+        today = datetime.now().date()
+        if qs == "浠婂ぉ":
+            st.session_state['main_process_start_date'] = today
+            st.session_state['main_process_end_date'] = today
+        elif qs == "鏈�杩�3澶�":
+            st.session_state['main_process_start_date'] = today - timedelta(days=3)
+            st.session_state['main_process_end_date'] = today
+        elif qs == "鏈�杩�7澶�":
+            st.session_state['main_process_start_date'] = today - timedelta(days=7)
+            st.session_state['main_process_end_date'] = today
+        elif qs == "鏈�杩�30澶�":
+            st.session_state['main_process_start_date'] = today - timedelta(days=30)
+            st.session_state['main_process_end_date'] = today
+
+    def on_date_change():
+        st.session_state['main_process_quick_select'] = "鑷畾涔�"
+
+    # 鏌ヨ鏉′欢鍖哄煙
+    with st.expander("馃攳 鏌ヨ閰嶇疆", expanded=True):
+        # 娣诲姞鑷畾涔� CSS 瀹炵幇鍝嶅簲寮忔崲琛�
+        st.markdown("""
+            <style>
+            /* 寮哄埗鍒楀鍣ㄦ崲琛� */
+            [data-testid="stExpander"] [data-testid="column"] {
+                flex: 1 1 120px !important;
+                min-width: 120px !important;
+            }
+            /* 閽堝鏃ユ湡杈撳叆妗嗗垪绋嶅井鍔犲涓�鐐� */
+            @media (min-width: 768px) {
+                [data-testid="stExpander"] [data-testid="column"]:nth-child(6),
+                [data-testid="stExpander"] [data-testid="column"]:nth-child(7) {
+                    flex: 2 1 180px !important;
+                    min-width: 180px !important;
+                }
+            }
+            </style>
+            """, 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['main_process_quick_select'] == option else "secondary"
+                if st.button(option, key=f"btn_main_{option}", width='stretch', type=button_type):
+                    update_dates(option)
+                    st.rerun()
+
+        with cols[5]:
+            st.date_input(
+                "寮�濮嬫棩鏈�", 
+                label_visibility="collapsed",
+                key="main_process_start_date",
+                on_change=on_date_change
+            )
+        
+        with cols[6]:
+            st.date_input(
+                "缁撴潫鏃ユ湡", 
+                label_visibility="collapsed",
+                key="main_process_end_date",
+                on_change=on_date_change
+            )
+
+        with cols[7]:
+            query_button = st.button("馃殌 鏌ヨ", key="main_process_query", width='stretch')
+
+    # 杞崲涓篸atetime瀵硅薄
+    start_dt = datetime.combine(st.session_state['main_process_start_date'], datetime.min.time())
+    end_dt = datetime.combine(st.session_state['main_process_end_date'], datetime.max.time())
+
+    if query_button:
+        with st.spinner("姝e湪鑾峰彇涓绘祦绋嬫暟鎹�..."):
+            # 1. 鑾峰彇涓婚�熷害鏁版嵁
+            df_speed = service.get_cutting_setting_data(start_dt, end_dt)
+            # 2. 鑾峰彇鐢垫満鐩戞帶鏁版嵁
+            df_motor = service.get_motor_monitoring_data(start_dt, end_dt)
+            # 3. 鑾峰彇娓╁害鎺у埗鏁版嵁
+            df_temp = service.get_temperature_control_data(start_dt, end_dt)
+
+            # --- 瓒嬪娍鍥� 1: 娴佺▼涓婚�熷害 ---
+            st.subheader("馃搱 娴佺▼涓婚�熷害瓒嬪娍")
+            if not df_speed.empty:
+                fig_speed = px.line(df_speed, x='time', y='process_main_speed', 
+                                   title="娴佺▼涓婚�熷害 (M/Min)",
+                                   labels={'time': '鏃堕棿', 'process_main_speed': '涓婚�熷害 (M/Min)'})
+                fig_speed.update_layout(xaxis=dict(rangeslider=dict(visible=True), type='date'))
+                st.plotly_chart(fig_speed, width='stretch', config={'scrollZoom': True})
+            else:
+                st.info("璇ユ椂闂存鍐呮棤涓婚�熷害鏁版嵁")
+
+            # --- 瓒嬪娍鍥� 2: 鐢垫満杩愯绾块�� ---
+            st.subheader("馃搱 鐢垫満杩愯绾块�熻秼鍔�")
+            if not df_motor.empty:
+                fig_motor = go.Figure()
+                fig_motor.add_trace(go.Scatter(x=df_motor['time'], y=df_motor['m1_line_speed'], name='鎷夊嚭涓�娈电嚎閫�'))
+                fig_motor.add_trace(go.Scatter(x=df_motor['time'], y=df_motor['m2_line_speed'], name='鎷夊嚭浜屾绾块��'))
+                fig_motor.update_layout(
+                    title="鐢垫満绾块�� (M/Min)", 
+                    xaxis_title="鏃堕棿", 
+                    yaxis_title="绾块�� (M/Min)",
+                    xaxis=dict(rangeslider=dict(visible=True), type='date')
+                )
+                st.plotly_chart(fig_motor, width='stretch', config={'scrollZoom': True})
+            else:
+                st.info("璇ユ椂闂存鍐呮棤鐢垫満鐩戞帶鏁版嵁")
+
+            # --- 瓒嬪娍鍥� 3: 涓敯鎸ゅ嚭鏈烘俯搴︽帶鍒� ---
+            st.subheader("馃搱 涓敯鎸ゅ嚭鏈烘俯搴﹁秼鍔�")
+            if not df_temp.empty:
+                fig_temp = go.Figure()
+                
+                # 铻烘潌娓╁害
+                fig_temp.add_trace(go.Scatter(x=df_temp['time'], y=df_temp['nakata_extruder_screw_set_temp'], 
+                                            name='铻烘潌璁惧畾', line=dict(dash='dash')))
+                fig_temp.add_trace(go.Scatter(x=df_temp['time'], y=df_temp['nakata_extruder_screw_display_temp'], 
+                                            name='铻烘潌鏄剧ず'))
+                
+                # 鍚庢満绛掓俯搴�
+                fig_temp.add_trace(go.Scatter(x=df_temp['time'], y=df_temp['nakata_extruder_rear_barrel_set_temp'], 
+                                            name='鍚庢満绛掕瀹�', line=dict(dash='dash')))
+                fig_temp.add_trace(go.Scatter(x=df_temp['time'], y=df_temp['nakata_extruder_rear_barrel_display_temp'], 
+                                            name='鍚庢満绛掓樉绀�'))
+                
+                # 鍓嶆満绛掓俯搴�
+                fig_temp.add_trace(go.Scatter(x=df_temp['time'], y=df_temp['nakata_extruder_front_barrel_set_temp'], 
+                                            name='鍓嶆満绛掕瀹�', line=dict(dash='dash')))
+                fig_temp.add_trace(go.Scatter(x=df_temp['time'], y=df_temp['nakata_extruder_front_barrel_display_temp'], 
+                                            name='鍓嶆満绛掓樉绀�'))
+                
+                # 鏈哄ご娓╁害
+                fig_temp.add_trace(go.Scatter(x=df_temp['time'], y=df_temp['nakata_extruder_head_set_temp'], 
+                                            name='鏈哄ご璁惧畾', line=dict(dash='dash')))
+                fig_temp.add_trace(go.Scatter(x=df_temp['time'], y=df_temp['nakata_extruder_head_display_temp'], 
+                                            name='鏈哄ご鏄剧ず'))
+
+                fig_temp.update_layout(
+                    title="涓敯鎸ゅ嚭鏈烘俯搴� (掳C)", 
+                    xaxis_title="鏃堕棿", 
+                    yaxis_title="娓╁害 (掳C)",
+                    xaxis=dict(rangeslider=dict(visible=True), type='date')
+                )
+                st.plotly_chart(fig_temp, width='stretch', config={'scrollZoom': True})
+            else:
+                st.info("璇ユ椂闂存鍐呮棤娓╁害鎺у埗鏁版嵁")
diff --git a/app/pages/sorting_dashboard.py b/app/pages/sorting_dashboard.py
new file mode 100644
index 0000000..b4d8576
--- /dev/null
+++ b/app/pages/sorting_dashboard.py
@@ -0,0 +1,416 @@
+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.data_query_service import DataQueryService
+from app.services.data_processing_service import DataProcessingService
+
+def show_sorting_dashboard():
+    # 鍒濆鍖栨湇鍔�
+    query_service = DataQueryService()
+    processing_service = DataProcessingService()
+
+    # 椤甸潰鏍囬
+    st.title("鍒嗘嫞纾呯Г鏁版嵁鍒嗘瀽")
+
+    # 鍒濆鍖栦細璇濈姸鎬佺敤浜庢棩鏈熷悓姝�
+    if 'sorting_start_date' not in st.session_state:
+        st.session_state['sorting_start_date'] = datetime.now().date() - timedelta(days=7)
+    if 'sorting_end_date' not in st.session_state:
+        st.session_state['sorting_end_date'] = datetime.now().date()
+    if 'sorting_quick_select' not in st.session_state:
+        st.session_state['sorting_quick_select'] = "鏈�杩�7澶�"
+
+    # 瀹氫箟鍥炶皟鍑芥暟
+    def update_dates(qs):
+        st.session_state['sorting_quick_select'] = qs
+        today = datetime.now().date()
+        if qs == "浠婂ぉ":
+            st.session_state['sorting_start_date'] = today
+            st.session_state['sorting_end_date'] = today
+        elif qs == "鏈�杩�3澶�":
+            st.session_state['sorting_start_date'] = today - timedelta(days=3)
+            st.session_state['sorting_end_date'] = today
+        elif qs == "鏈�杩�7澶�":
+            st.session_state['sorting_start_date'] = today - timedelta(days=7)
+            st.session_state['sorting_end_date'] = today
+        elif qs == "鏈�杩�30澶�":
+            st.session_state['sorting_start_date'] = today - timedelta(days=30)
+            st.session_state['sorting_end_date'] = today
+
+    def on_date_change():
+        st.session_state['sorting_quick_select'] = "鑷畾涔�"
+
+    # 鏌ヨ鏉′欢鍖哄煙
+    with st.expander("馃攳 鏌ヨ閰嶇疆", expanded=True):
+        # 娣诲姞鑷畾涔� CSS 瀹炵幇鍝嶅簲寮忔崲琛�
+        st.markdown("""
+            <style>
+            /* 寮哄埗鍒楀鍣ㄦ崲琛� */
+            [data-testid="stExpander"] [data-testid="column"] {
+                flex: 1 1 120px !important;
+                min-width: 120px !important;
+            }
+            /* 閽堝鏃ユ湡杈撳叆妗嗗垪绋嶅井鍔犲涓�鐐� */
+            @media (min-width: 768px) {
+                [data-testid="stExpander"] [data-testid="column"]:nth-child(6),
+                [data-testid="stExpander"] [data-testid="column"]:nth-child(7) {
+                    flex: 2 1 180px !important;
+                    min-width: 180px !important;
+                }
+            }
+            </style>
+            """, 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['sorting_quick_select'] == option else "secondary"
+                if st.button(option, key=f"btn_{option}", width='stretch', type=button_type):
+                    update_dates(option)
+                    st.rerun()
+
+        with cols[5]:
+            start_date = st.date_input(
+                "寮�濮嬫棩鏈�", 
+                label_visibility="collapsed",
+                key="sorting_start_date",
+                on_change=on_date_change
+            )
+        
+        with cols[6]:
+            end_date = st.date_input(
+                "缁撴潫鏃ユ湡", 
+                label_visibility="collapsed",
+                key="sorting_end_date",
+                on_change=on_date_change
+            )
+
+        with cols[7]:
+            query_button = st.button("馃殌 鏌ヨ", key="sorting_query", width='stretch')
+
+    # 杞崲涓篸atetime瀵硅薄锛堝寘鍚椂闂达級
+    start_datetime = datetime.combine(start_date, datetime.min.time())
+    end_datetime = datetime.combine(end_date, datetime.max.time())
+
+    # 鏌ヨ鎸夐挳澶勭悊
+    if query_button:
+        # 楠岃瘉鏃ユ湡鑼冨洿
+        if start_datetime > end_datetime:
+            st.error("寮�濮嬫棩鏈熶笉鑳芥櫄浜庣粨鏉熸棩鏈燂紒")
+        else:
+            # 鏄剧ず鍔犺浇鐘舵��
+            with st.spinner("姝e湪鏌ヨ鏁版嵁..."):
+                # 鏌ヨ鏁版嵁
+                raw_data = query_service.get_sorting_scale_data(start_datetime, end_datetime)
+                
+                if raw_data is None or raw_data.empty:
+                    st.warning("鏈煡璇㈠埌鏁版嵁锛岃妫�鏌ユ棩鏈熻寖鍥存垨鏁版嵁搴撹繛鎺ワ紒")
+                    st.session_state['query_results'] = None
+                else:
+                    # 娓呮礂鏁版嵁
+                    cleaned_data = processing_service.clean_data(raw_data)
+                    
+                    # 璁$畻缁熻淇℃伅
+                    stats = processing_service.calculate_statistics(cleaned_data)
+                    
+                    # 鍒嗘瀽鏋佸�肩偣
+                    extreme_analysis = processing_service.analyze_extreme_points(cleaned_data)
+                    extreme_points = extreme_analysis['extreme_points']
+                    phase_maxima = extreme_analysis['phase_maxima']
+                    overall_pass_rate = extreme_analysis['overall_pass_rate']
+                    
+                    # 缂撳瓨缁撴灉
+                    st.session_state['query_results'] = {
+                        'cleaned_data': cleaned_data,
+                        'stats': stats,
+                        'extreme_points': extreme_points,
+                        'phase_maxima': phase_maxima,
+                        'overall_pass_rate': overall_pass_rate
+                    }
+                    
+                    # 鏄剧ず鏁版嵁姒傝
+                    st.subheader("鏁版嵁姒傝")
+                    col1, col2, col3, col4 = st.columns(4)
+                    
+                    with col1:
+                        st.metric("鎬昏褰曟暟", stats.get('total_records', 0))
+                    
+                    with col2:
+                        st.metric("骞冲潎鍚堟牸鏁�", round(stats.get('count_in_range', {}).get('mean', 0), 2))
+                    
+                    with col3:
+                        st.metric("鏁版嵁鏃堕棿鑼冨洿", f"{cleaned_data['time'].min()} 鑷� {cleaned_data['time'].max()}")
+                    
+                    with col4:
+                        st.metric("鏁翠綋鍚堟牸鐜�", f"{overall_pass_rate}%")
+                    
+                    # 鏄剧ず瓒嬪娍鍥�
+                    st.subheader("鏁版嵁瓒嬪娍鍥�")
+                    fig = px.line(
+                        cleaned_data,
+                        x='time',
+                        y=['count_under', 'count_in_range', 'count_over'],
+                        labels={
+                            'time': '鏃堕棿',
+                            'value': '鏁伴噺',
+                            'variable': '鏁版嵁绫诲瀷'
+                        },
+                        title='鍒嗘嫞纾呯Г鏁版嵁瓒嬪娍',
+                        color_discrete_map={
+                            'count_under': 'red',
+                            'count_in_range': 'green',
+                            'count_over': 'blue'
+                        }
+                    )
+                    
+                    # 鑷畾涔夊浘渚�
+                    fig.for_each_trace(lambda t: t.update(name={
+                        'count_under': '浣庝簬鏍囧噯',
+                        'count_in_range': '鍦ㄦ爣鍑嗚寖鍥村唴',
+                        'count_over': '楂樹簬鏍囧噯'
+                    }[t.name]))
+                    
+                    # 閰嶇疆鍥捐〃缂╂斁鍔熻兘
+                    fig.update_layout(
+                        xaxis=dict(
+                            fixedrange=False,
+                            rangeslider=dict(visible=True)
+                        ),
+                        yaxis=dict(fixedrange=False),
+                        dragmode='zoom'
+                    )
+                    
+                    # 閰嶇疆鍥捐〃鍙傛暟
+                    config = {'scrollZoom': True}
+                    
+                    # 鏄剧ず鍥捐〃
+                    st.plotly_chart(fig, width='stretch', config=config)
+       
+                    # 鏄剧ず鏋佸�肩偣鍒嗘瀽
+                    st.subheader("鏋佸�肩偣鍒嗘瀽")
+                    if not extreme_points.empty:
+                        # 鍑嗗灞曠ず鏁版嵁
+                        display_df = extreme_points[['time', 'count_under', 'count_in_range', 'count_over', 'pass_rate']].copy()
+                        
+                        # 鏍煎紡鍖栨椂闂存埑
+                        display_df['time'] = display_df['time'].dt.strftime('%Y-%m-%d %H:%M:%S')
+                        
+                        # 淇敼鍒楀悕
+                        display_df.columns = ['鏃堕棿鎴�', '瓒呬笅闄愭暟鍊�', '鑼冨洿鍐呮暟鍊�', '瓒呬笂闄愭暟鍊�', '鍚堟牸鐜�(%)']
+                        
+                        # 鏄剧ず鏁版嵁琛ㄦ牸
+                        st.dataframe(display_df, use_container_width=True)
+                        
+                        # 鏄剧ず鏋佸�肩偣鏁伴噺
+                        st.info(f"鍏辫瘑鍒埌 {len(extreme_points)} 涓瀬鍊肩偣")
+                        
+                        # 娣诲姞瀵煎嚭鍔熻兘
+                        import io
+                        
+                        # 鍒涘缓CSV鏁版嵁
+                        csv_buffer = io.StringIO()
+                        display_df.to_csv(csv_buffer, index=False, encoding='utf-8-sig')
+                        csv_data = csv_buffer.getvalue()
+                        
+                        # 娣诲姞涓嬭浇鎸夐挳
+                        st.download_button(
+                            label="涓嬭浇鏋佸�肩偣鍒嗘瀽缁撴灉",
+                            data=csv_data,
+                            file_name=f"鏋佸�肩偣鍒嗘瀽_{start_date}_{end_date}.csv",
+                            mime="text/csv"
+                        )
+                    else:
+                        st.warning("鏈瘑鍒埌鏋佸�肩偣")
+                
+                                 
+                    # 鏄剧ず閲嶉噺瓒嬪娍鍥�
+                    st.subheader("閲嶉噺瓒嬪娍鍥�")
+                    if 'weight' in cleaned_data.columns:
+                        # 鍒涘缓鍥捐〃
+                        weight_fig = go.Figure()
+                        
+                        # 妫�鏌ユ槸鍚﹀寘鍚槇鍊肩浉鍏冲瓧娈�
+                        has_thresholds = all(col in cleaned_data.columns for col in ['baseline_value', 'over_difference', 'under_difference'])
+                        
+                        # 璁$畻鍔ㄦ�侀槇鍊�
+                        if has_thresholds:
+                            # 澶嶅埗鏁版嵁浠ラ伩鍏嶄慨鏀瑰師濮嬫暟鎹�
+                            threshold_data = cleaned_data.copy()
+                            
+                            # 澶勭悊闆跺��
+                            for col in ['baseline_value', 'over_difference', 'under_difference']:
+                                threshold_data[col] = threshold_data[col].replace(0, pd.NA)
+                            
+                            # 鍚戝墠濉厖缂哄け鍊�
+                            threshold_data = threshold_data.ffill()
+                            
+                            # 璁$畻涓婁笅闄愰槇鍊�
+                            threshold_data['upper_threshold'] = threshold_data['over_difference']
+                            threshold_data['lower_threshold'] = threshold_data['under_difference']
+                            
+                            # 鏍囪瓒呭嚭闃堝�肩殑鐐�
+                            threshold_data['is_out_of_range'] = (threshold_data['weight'] > threshold_data['upper_threshold']) | (threshold_data['weight'] < threshold_data['lower_threshold'])
+                            
+                            # 娣诲姞鍩哄噯鍊肩嚎锛堝姩鎬侊級
+                            weight_fig.add_trace(go.Scatter(
+                                x=threshold_data['time'],
+                                y=threshold_data['baseline_value'],
+                                name='鍩哄噯鍊�',
+                                line=dict(color='green', width=2),
+                                opacity=0.7
+                            ))
+                            
+                            # 娣诲姞涓婇檺闃堝�肩嚎锛堝姩鎬侊級
+                            weight_fig.add_trace(go.Scatter(
+                                x=threshold_data['time'],
+                                y=threshold_data['upper_threshold'],
+                                name='涓婇檺闃堝��',
+                                line=dict(color='red', width=2),
+                                opacity=0.7
+                            ))
+                            
+                            # 娣诲姞涓嬮檺闃堝�肩嚎锛堝姩鎬侊級
+                            weight_fig.add_trace(go.Scatter(
+                                x=threshold_data['time'],
+                                y=threshold_data['lower_threshold'],
+                                name='涓嬮檺闃堝��',
+                                line=dict(color='orange', width=2),
+                                opacity=0.7
+                            ))
+                            
+                            # 鍒嗙姝e父鍜屽紓甯告暟鎹偣
+                            normal_data = threshold_data[~threshold_data['is_out_of_range']]
+                            out_of_range_data = threshold_data[threshold_data['is_out_of_range']]
+                            
+                            # 娣诲姞姝e父閲嶉噺鐐�
+                            weight_fig.add_trace(go.Scatter(
+                                x=normal_data['time'],
+                                y=normal_data['weight'],
+                                name='閲嶉噺 (姝e父)',
+                                opacity=0.8,
+                                mode='markers',
+                                marker=dict(
+                                    size=4,
+                                    color='blue',
+                                    symbol='circle',
+                                    line=dict(width=0, color='blue')
+                                )
+                            ))
+                            
+                            # 娣诲姞寮傚父閲嶉噺鐐�
+                            if not out_of_range_data.empty:
+                                weight_fig.add_trace(go.Scatter(
+                                    x=out_of_range_data['time'],
+                                    y=out_of_range_data['weight'],
+                                    name='閲嶉噺 (寮傚父)',
+                                    opacity=0.8,
+                                    mode='markers',
+                                    marker=dict(
+                                        size=4,
+                                        color='red',
+                                        symbol='triangle-up',
+                                        line=dict(width=2, color='darkred')
+                                    )
+                                ))
+                        else:
+                            # 娌℃湁闃堝�兼暟鎹紝鍙樉绀洪噸閲忚秼鍔�
+                            weight_fig.add_trace(go.Scatter(
+                                x=cleaned_data['time'],
+                                y=cleaned_data['weight'],
+                                name='閲嶉噺',
+                                line=dict(color='blue', width=2),
+                                opacity=0.8
+                            ))
+                            st.warning("鏁版嵁涓笉鍖呭惈闃堝�肩浉鍏冲瓧娈碉紝鏃犳硶鏄剧ず闃堝�肩嚎鍜屽紓甯歌绀猴紒")
+                        
+                        # 閰嶇疆鍥捐〃甯冨眬
+                        weight_fig.update_layout(
+                            title='閲嶉噺闅忔椂闂村彉鍖栬秼鍔�',
+                            xaxis_title='鏃堕棿',
+                            yaxis_title='閲嶉噺',
+                            xaxis=dict(
+                                rangeslider=dict(visible=True),
+                                type='date',
+                                fixedrange=False
+                            ),
+                            yaxis=dict(fixedrange=False),
+                            legend=dict(
+                                orientation="h",
+                                yanchor="bottom",
+                                y=1.02,
+                                xanchor="right",
+                                x=1
+                            ),
+                            hovermode='x unified',
+                            height=600,
+                            dragmode='zoom',
+                            updatemenus=[
+                                dict(
+                                    type="buttons",
+                                    direction="left",
+                                    buttons=list([
+                                        dict(args=["visible", [True, True, True, True, True]], label="鏄剧ず鍏ㄩ儴", method="restyle"),
+                                        dict(args=["visible", [False, False, False, True, True]], label="浠呮樉绀洪噸閲�", method="restyle"),
+                                        dict(args=["visible", [True, True, True, False, False]], label="浠呮樉绀洪槇鍊�", method="restyle"),
+                                        dict(args=["visible", [True, True, True, True, False]], label="鏄剧ず姝e父閲嶉噺", method="restyle"),
+                                        dict(args=["visible", [True, True, True, False, True]], label="鏄剧ず寮傚父閲嶉噺", method="restyle")
+                                    ]),
+                                    pad={"r": 10, "t": 10},
+                                    showactive=True,
+                                    x=0.1,
+                                    xanchor="left",
+                                    y=1.1,
+                                    yanchor="top"
+                                ),
+                            ]
+                        )
+                        
+                        # 鏄剧ず鍥捐〃
+                        st.plotly_chart(weight_fig, width='stretch', config={'scrollZoom': True})
+                    
+                    # 鏄剧ず鏁版嵁琛ㄦ牸
+                    st.subheader("鍘熷鏁版嵁")
+                    st.dataframe(cleaned_data, use_container_width=True)
+                    
+                    # 鏄剧ず璇︾粏缁熻淇℃伅
+                    if stats:
+                        st.subheader("璇︾粏缁熻淇℃伅")
+                        with st.expander("鏌ョ湅璇︾粏缁熻"):
+                            col_stats1, col_stats2, col_stats3 = st.columns(3)
+                            
+                            with col_stats1:
+                                st.write("**浣庝簬鏍囧噯**")
+                                st.write(f"骞冲潎鍊�: {round(stats['count_under']['mean'], 2)}")
+                                st.write(f"鎬诲拰: {stats['count_under']['sum']}")
+                                st.write(f"鏈�澶у��: {stats['count_under']['max']}")
+                                st.write(f"鏈�灏忓��: {stats['count_under']['min']}")
+                            
+                            with col_stats2:
+                                st.write("**鍦ㄦ爣鍑嗚寖鍥村唴**")
+                                st.write(f"骞冲潎鍊�: {round(stats['count_in_range']['mean'], 2)}")
+                                st.write(f"鎬诲拰: {stats['count_in_range']['sum']}")
+                                st.write(f"鏈�澶у��: {stats['count_in_range']['max']}")
+                                st.write(f"鏈�灏忓��: {stats['count_in_range']['min']}")
+                            
+                            with col_stats3:
+                                st.write("**楂樹簬鏍囧噯**")
+                                st.write(f"骞冲潎鍊�: {round(stats['count_over']['mean'], 2)}")
+                                st.write(f"鎬诲拰: {stats['count_over']['sum']}")
+                                st.write(f"鏈�澶у��: {stats['count_over']['max']}")
+                                st.write(f"鏈�灏忓��: {stats['count_over']['min']}")
+
+    # 鏁版嵁搴撹繛鎺ョ姸鎬�
+    st.sidebar.subheader("鏁版嵁搴撶姸鎬�")
+    if query_service.db.is_connected():
+        st.sidebar.success("鏁版嵁搴撹繛鎺ユ甯�")
+    else:
+        st.sidebar.warning("鏁版嵁搴撴湭杩炴帴")
+
+if __name__ == "__main__":
+    show_sorting_dashboard()
diff --git a/app/services/data_processing_service.py b/app/services/data_processing_service.py
index 5a2d3aa..3a7bc05 100644
--- a/app/services/data_processing_service.py
+++ b/app/services/data_processing_service.py
@@ -18,24 +18,15 @@
             # 澶勭悊缂哄け鍊�
             cleaned_df = cleaned_df.fillna(0)
             
-            # 纭繚鏁版嵁绫诲瀷姝g‘
-            cleaned_df['count_under'] = cleaned_df['count_under'].astype(int)
-            cleaned_df['count_in_range'] = cleaned_df['count_in_range'].astype(int)
-            cleaned_df['count_over'] = cleaned_df['count_over'].astype(int)
+            # 纭繚鏁版嵁绫诲瀷姝g‘锛堜粎褰撳垪瀛樺湪鏃讹級
+            for col in ['count_under', 'count_in_range', 'count_over']:
+                if col in cleaned_df.columns:
+                    cleaned_df[col] = cleaned_df[col].astype(int)
             
             # 纭繚time鏄痙atetime绫诲瀷骞跺鐞嗘椂鍖�
             if 'time' in cleaned_df.columns:
                 # 杞崲涓篸atetime绫诲瀷
                 cleaned_df['time'] = pd.to_datetime(cleaned_df['time'])
-                
-                # 澶勭悊鏃跺尯
-                # 妫�鏌ユ槸鍚﹀凡缁忔湁鏃跺尯淇℃伅
-                if cleaned_df['time'].dt.tz is None:
-                    # 濡傛灉娌℃湁鏃跺尯淇℃伅锛屽亣璁炬槸UTC鏃堕棿骞舵坊鍔犳椂鍖�
-                    cleaned_df['time'] = cleaned_df['time'].dt.tz_localize('UTC')
-                
-                # 杞崲涓轰笂娴锋椂鍖猴紙UTC+8锛�
-                cleaned_df['time'] = cleaned_df['time'].dt.tz_convert('Asia/Shanghai')
             
             return cleaned_df
         except Exception as e:
@@ -53,26 +44,18 @@
         
         try:
             stats = {
-                'total_records': len(df),
-                'count_under': {
-                    'mean': df['count_under'].mean(),
-                    'sum': df['count_under'].sum(),
-                    'max': df['count_under'].max(),
-                    'min': df['count_under'].min()
-                },
-                'count_in_range': {
-                    'mean': df['count_in_range'].mean(),
-                    'sum': df['count_in_range'].sum(),
-                    'max': df['count_in_range'].max(),
-                    'min': df['count_in_range'].min()
-                },
-                'count_over': {
-                    'mean': df['count_over'].mean(),
-                    'sum': df['count_over'].sum(),
-                    'max': df['count_over'].max(),
-                    'min': df['count_over'].min()
-                }
+                'total_records': len(df)
             }
+            
+            # 浠呭綋鍒楀瓨鍦ㄦ椂璁$畻缁熻淇℃伅
+            for col in ['count_under', 'count_in_range', 'count_over']:
+                if col in df.columns:
+                    stats[col] = {
+                        'mean': df[col].mean(),
+                        'sum': df[col].sum(),
+                        'max': df[col].max(),
+                        'min': df[col].min()
+                    }
             return stats
         except Exception as e:
             print(f"璁$畻缁熻淇℃伅澶辫触: {e}")
diff --git a/app/services/data_query_service.py b/app/services/data_query_service.py
index fee3764..4f94242 100644
--- a/app/services/data_query_service.py
+++ b/app/services/data_query_service.py
@@ -1,25 +1,31 @@
 import pandas as pd
 from functools import lru_cache
+from datetime import timedelta
 from app.database.database import DatabaseConnection
 
 class DataQueryService:
     def __init__(self):
         self.db = DatabaseConnection()
+        self.timezone_offset = 8  # 榛樿涓滃叓鍖猴紙鍖椾含鏃堕棿锛�
     
     def get_sorting_scale_data(self, start_date, end_date):
         """
         鏌ヨ鍒嗘嫞纾呯Г鏁版嵁
-        :param start_date: 寮�濮嬫棩鏈�
-        :param end_date: 缁撴潫鏃ユ湡
-        :return: 鍖呭惈count_under, count_in_range, count_over鐨勬暟鎹
+        :param start_date: 寮�濮嬫棩鏈� (鏈湴鏃堕棿)
+        :param end_date: 缁撴潫鏃ユ湡 (鏈湴鏃堕棿)
+        :return: 鍖呭惈count_under, count_in_range, count_over鐨勬暟鎹 (杩斿洖鏈湴鏃堕棿)
         """
         try:
+            # 灏嗘湰鍦版椂闂磋浆鎹负UTC鏃堕棿杩涜鏌ヨ
+            start_date_utc = start_date - timedelta(hours=self.timezone_offset)
+            end_date_utc = end_date - timedelta(hours=self.timezone_offset)
+
             # 杩炴帴鏁版嵁搴�
             if not self.db.is_connected():
                 if not self.db.connect():
                     return None
             
-            connection = self.db.get_connection()
+            # connection = self.db.get_connection()
             
             # SQL鏌ヨ璇彞
             query = """
@@ -41,7 +47,11 @@
             """
             
             # 鎵ц鏌ヨ骞惰浆鎹负DataFrame
-            df = pd.read_sql(query, connection, params=(start_date, end_date))
+            df = pd.read_sql(query, self.db.get_connection(), params=(start_date_utc, end_date_utc))
+            
+            # 灏嗘煡璇㈢粨鏋滀腑鐨刄TC鏃堕棿杞崲鍥炴湰鍦版椂闂�
+            if not df.empty and 'time' in df.columns:
+                df['time'] = pd.to_datetime(df['time']) + timedelta(hours=self.timezone_offset)
             
             return df
         except Exception as e:
diff --git a/app/services/extruder_service.py b/app/services/extruder_service.py
index 4ecfd70..b22eed3 100644
--- a/app/services/extruder_service.py
+++ b/app/services/extruder_service.py
@@ -1,19 +1,25 @@
 import pandas as pd
 from functools import lru_cache
+from datetime import timedelta
 from app.database.database import DatabaseConnection
 
 class ExtruderService:
     def __init__(self):
         self.db = DatabaseConnection()
+        self.timezone_offset = 8  # 榛樿涓滃叓鍖猴紙鍖椾含鏃堕棿锛�
     
     def get_extruder_data(self, start_date, end_date):
         """
         鏌ヨ鎸ゅ嚭鏈烘暟鎹�
-        :param start_date: 寮�濮嬫棩鏈�
-        :param end_date: 缁撴潫鏃ユ湡
-        :return: 鍖呭惈鎸ゅ嚭鏈烘暟鎹殑鏁版嵁妗�
+        :param start_date: 寮�濮嬫棩鏈� (鏈湴鏃堕棿)
+        :param end_date: 缁撴潫鏃ユ湡 (鏈湴鏃堕棿)
+        :return: 鍖呭惈鎸ゅ嚭鏈烘暟鎹殑鏁版嵁妗� (杩斿洖鏈湴鏃堕棿)
         """
         try:
+            # 灏嗘湰鍦版椂闂磋浆鎹负UTC鏃堕棿杩涜鏌ヨ
+            start_date_utc = start_date - timedelta(hours=self.timezone_offset)
+            end_date_utc = end_date - timedelta(hours=self.timezone_offset)
+
             # 杩炴帴鏁版嵁搴�
             if not self.db.is_connected():
                 if not self.db.connect():
@@ -47,7 +53,11 @@
             """
             
             # 鎵ц鏌ヨ骞惰浆鎹负DataFrame
-            df = pd.read_sql(query, connection, params=(start_date, end_date))
+            df = pd.read_sql(query, connection, params=(start_date_utc, end_date_utc))
+            
+            # 灏嗘煡璇㈢粨鏋滀腑鐨刄TC鏃堕棿杞崲鍥炴湰鍦版椂闂�
+            if not df.empty and 'time' in df.columns:
+                df['time'] = pd.to_datetime(df['time']) + timedelta(hours=self.timezone_offset)
             
             return df
         except Exception as e:
@@ -75,9 +85,8 @@
             batch_df['compound_code_shift'] = batch_df['compound_code'].shift(1)
             # 鑻ュ綋鍓嶈 compound_code 涓庡墠涓�琛屼笉鍚岋紝鍒欐爣璁颁负鎹㈡壒锛�1锛夛紝鍚﹀垯涓� 0 锛岀涓�琛岀壒娈婂鐞嗕负 0
             batch_df['is_batch_change'] = (batch_df['compound_code'] != batch_df['compound_code_shift']).astype(int)
-            batch_df['is_batch_change'].iloc[0] = 0
-            # 鎵撳嵃batch_df
-            print(batch_df)
+            batch_df.loc[batch_df.index[0], 'is_batch_change'] = 0
+            
             # 鎻愬彇鎵�鏈夋崲鎵逛簨浠剁殑绱㈠紩
             change_indices = batch_df[batch_df['is_batch_change'] == 1].index.tolist()
             
diff --git a/app/services/main_process_service.py b/app/services/main_process_service.py
new file mode 100644
index 0000000..b25c3c2
--- /dev/null
+++ b/app/services/main_process_service.py
@@ -0,0 +1,88 @@
+import pandas as pd
+from datetime import timedelta
+from app.database.database import DatabaseConnection
+
+class MainProcessService:
+    def __init__(self):
+        self.db = DatabaseConnection()
+        self.timezone_offset = 8  # 榛樿涓滃叓鍖猴紙鍖椾含鏃堕棿锛�
+    
+    def _to_utc(self, dt):
+        return dt - timedelta(hours=self.timezone_offset)
+    
+    def _to_local(self, df):
+        if not df.empty and 'time' in df.columns:
+            df['time'] = pd.to_datetime(df['time']) + timedelta(hours=self.timezone_offset)
+        return df
+
+    def get_cutting_setting_data(self, start_date, end_date):
+        """鑾峰彇娴佺▼涓婚�熷害鏁版嵁"""
+        try:
+            start_utc = self._to_utc(start_date)
+            end_utc = self._to_utc(end_date)
+            
+            if not self.db.is_connected():
+                self.db.connect()
+            
+            query = """
+            SELECT time, process_main_speed 
+            FROM public.aics_main_process_cutting_setting 
+            WHERE time BETWEEN %s AND %s 
+            ORDER BY time ASC
+            """
+            df = pd.read_sql(query, self.db.get_connection(), params=(start_utc, end_utc))
+            return self._to_local(df)
+        except Exception as e:
+            print(f"鑾峰彇涓婚�熷害鏁版嵁澶辫触: {e}")
+            return pd.DataFrame()
+
+    def get_motor_monitoring_data(self, start_date, end_date):
+        """鑾峰彇鐢垫満鐩戞帶绾块�熸暟鎹�"""
+        try:
+            start_utc = self._to_utc(start_date)
+            end_utc = self._to_utc(end_date)
+            
+            if not self.db.is_connected():
+                self.db.connect()
+            
+            query = """
+            SELECT time, m1_line_speed, m2_line_speed 
+            FROM public.aics_main_process_motor_monitoring 
+            WHERE time BETWEEN %s AND %s 
+            ORDER BY time ASC
+            """
+            df = pd.read_sql(query, self.db.get_connection(), params=(start_utc, end_utc))
+            return self._to_local(df)
+        except Exception as e:
+            print(f"鑾峰彇鐢垫満鐩戞帶鏁版嵁澶辫触: {e}")
+            return pd.DataFrame()
+
+    def get_temperature_control_data(self, start_date, end_date):
+        """鑾峰彇涓敯鎸ゅ嚭鏈烘俯搴﹁瀹氫笌鏄剧ず鏁版嵁"""
+        try:
+            start_utc = self._to_utc(start_date)
+            end_utc = self._to_utc(end_date)
+            
+            if not self.db.is_connected():
+                self.db.connect()
+            
+            query = """
+            SELECT 
+                time,
+                nakata_extruder_screw_set_temp,
+                nakata_extruder_screw_display_temp,
+                nakata_extruder_rear_barrel_set_temp,
+                nakata_extruder_rear_barrel_display_temp,
+                nakata_extruder_front_barrel_set_temp,
+                nakata_extruder_front_barrel_display_temp,
+                nakata_extruder_head_set_temp,
+                nakata_extruder_head_display_temp
+            FROM public.aics_main_process_temperature_control_setting 
+            WHERE time BETWEEN %s AND %s 
+            ORDER BY time ASC
+            """
+            df = pd.read_sql(query, self.db.get_connection(), params=(start_utc, end_utc))
+            return self._to_local(df)
+        except Exception as e:
+            print(f"鑾峰彇娓╁害鎺у埗鏁版嵁澶辫触: {e}")
+            return pd.DataFrame()
diff --git a/dashboard.py b/dashboard.py
index 2850f76..da7aaf1 100644
--- a/dashboard.py
+++ b/dashboard.py
@@ -1,10 +1,8 @@
 import streamlit as st
-import plotly.express as px
-import pandas as pd
-from datetime import datetime, timedelta
-from app.services.data_query_service import DataQueryService
-from app.services.data_processing_service import DataProcessingService
-from app.services.extruder_service import ExtruderService
+from app.pages.sorting_dashboard import show_sorting_dashboard
+from app.pages.extruder_dashboard import show_extruder_dashboard
+from app.pages.main_process_dashboard import show_main_process_dashboard
+from app.pages.comprehensive_dashboard import show_comprehensive_dashboard
 
 # 璁剧疆椤甸潰閰嶇疆
 st.set_page_config(
@@ -13,722 +11,48 @@
     layout="wide"
 )
 
-# 宸︿晶鑿滃崟瀵艰埅
-st.sidebar.title("绯荤粺瀵艰埅")
-menu = st.sidebar.radio(
-    "閫夋嫨鍒嗘瀽妯″潡",
-    ["鍒嗘嫞纾呯Г", "鎸ゅ嚭鏈�"],
-    index=0,
-    key="main_menu"
+# 瀹氫箟椤甸潰
+sorting_page = st.Page(
+    show_sorting_dashboard, 
+    title="鍒嗘嫞纾呯Г", 
+    icon="鈿栵笍", 
+    url_path="sorting"
 )
 
-# 鍙充晶鍐呭鍖哄煙
-if menu == "鍒嗘嫞纾呯Г":
-    # 鍒濆鍖栨湇鍔�
-    query_service = DataQueryService()
-    processing_service = DataProcessingService()
+extruder_page = st.Page(
+    show_extruder_dashboard, 
+    title="鎸ゅ嚭鏈�", 
+    icon="馃彮", 
+    url_path="extruder"
+)
 
-    # 椤甸潰鏍囬
-    st.title("鍒嗘嫞纾呯Г鏁版嵁鍒嗘瀽")
+main_process_page = st.Page(
+    show_main_process_dashboard,
+    title="涓绘祦绋嬫帶鍒�",
+    icon="鈿欙笍",
+    url_path="main_process"
+)
 
-    # 鏌ヨ鏉′欢鍖哄煙锛堣縼绉诲埌鍙充晶椤堕儴锛�
-    st.subheader("鏌ヨ閰嶇疆")
-    col1, col2, col3 = st.columns([2, 2, 1])
-    
-    with col1:
-        start_date = st.date_input("寮�濮嬫棩鏈�", datetime.now() - timedelta(days=7), key="sorting_start_date")
-    
-    with col2:
-        end_date = st.date_input("缁撴潫鏃ユ湡", datetime.now(), key="sorting_end_date")
-    
-    with col3:
-        st.write("")  # 鍗犱綅
-        query_button = st.button("鏌ヨ鏁版嵁", key="sorting_query")
+comprehensive_page = st.Page(
+    show_comprehensive_dashboard,
+    title="缁煎悎鍒嗘瀽",
+    icon="馃寪",
+    url_path="comprehensive"
+)
 
-    # 杞崲涓篸atetime瀵硅薄锛堝寘鍚椂闂达級
-    start_datetime = datetime.combine(start_date, datetime.min.time())
-    end_datetime = datetime.combine(end_date, datetime.max.time())
+# 渚ц竟鏍忛〉鑴氫俊鎭�
+def show_footer():
+    st.sidebar.markdown("---")
+    st.sidebar.markdown("漏 2026 鏁版嵁鍒嗘瀽绯荤粺")
 
-    # 鏌ヨ鎸夐挳澶勭悊
-    if query_button:
-                # 楠岃瘉鏃ユ湡鑼冨洿
-                if start_datetime > end_datetime:
-                    st.error("寮�濮嬫棩鏈熶笉鑳芥櫄浜庣粨鏉熸棩鏈燂紒")
-                else:
-                    # 鏄剧ず鍔犺浇鐘舵��
-                    with st.spinner("姝e湪鏌ヨ鏁版嵁..."):
-                        # 鏌ヨ鏁版嵁
-                        raw_data = query_service.get_sorting_scale_data(start_datetime, end_datetime)
-                        
-                        if raw_data is None or raw_data.empty:
-                            st.warning("鏈煡璇㈠埌鏁版嵁锛岃妫�鏌ユ棩鏈熻寖鍥存垨鏁版嵁搴撹繛鎺ワ紒")
-                            st.session_state['query_results'] = None
-                        else:
-                            # 娓呮礂鏁版嵁
-                            cleaned_data = processing_service.clean_data(raw_data)
-                            
-                            # 璁$畻缁熻淇℃伅
-                            stats = processing_service.calculate_statistics(cleaned_data)
-                            
-                            # 鍒嗘瀽鏋佸�肩偣
-                            extreme_analysis = processing_service.analyze_extreme_points(cleaned_data)
-                            extreme_points = extreme_analysis['extreme_points']
-                            phase_maxima = extreme_analysis['phase_maxima']
-                            overall_pass_rate = extreme_analysis['overall_pass_rate']
-                            
-                            # 缂撳瓨缁撴灉
-                            st.session_state['query_results'] = {
-                                'cleaned_data': cleaned_data,
-                                'stats': stats,
-                                'extreme_points': extreme_points,
-                                'phase_maxima': phase_maxima,
-                                'overall_pass_rate': overall_pass_rate
-                            }
-                            
-                            # 鏄剧ず鏁版嵁姒傝
-                            st.subheader("鏁版嵁姒傝")
-                            col1, col2, col3, col4 = st.columns(4)
-                            
-                            with col1:
-                                st.metric("鎬昏褰曟暟", stats.get('total_records', 0))
-                            
-                            with col2:
-                                st.metric("骞冲潎鍚堟牸鏁�", round(stats.get('count_in_range', {}).get('mean', 0), 2))
-                            
-                            with col3:
-                                st.metric("鏁版嵁鏃堕棿鑼冨洿", f"{cleaned_data['time'].min()} 鑷� {cleaned_data['time'].max()}")
-                            
-                            with col4:
-                                st.metric("鏁翠綋鍚堟牸鐜�", f"{overall_pass_rate}%")
-                            
-                            # 鏄剧ず瓒嬪娍鍥�
-                            st.subheader("鏁版嵁瓒嬪娍鍥�")
-                            fig = px.line(
-                                cleaned_data,
-                                x='time',
-                                y=['count_under', 'count_in_range', 'count_over'],
-                                labels={
-                                    'time': '鏃堕棿',
-                                    'value': '鏁伴噺',
-                                    'variable': '鏁版嵁绫诲瀷'
-                                },
-                                title='鍒嗘嫞纾呯Г鏁版嵁瓒嬪娍',
-                                color_discrete_map={
-                                    'count_under': 'red',
-                                    'count_in_range': 'green',
-                                    'count_over': 'blue'
-                                }
-                            )
-                            
-                            # 鑷畾涔夊浘渚�
-                            fig.for_each_trace(lambda t: t.update(name={
-                                'count_under': '浣庝簬鏍囧噯',
-                                'count_in_range': '鍦ㄦ爣鍑嗚寖鍥村唴',
-                                'count_over': '楂樹簬鏍囧噯'
-                            }[t.name]))
-                            
-                            # 閰嶇疆鍥捐〃缂╂斁鍔熻兘
-                            fig.update_layout(
-                                xaxis=dict(
-                                    fixedrange=False
-                                ),
-                                yaxis=dict(
-                                    fixedrange=False
-                                ),
-                                dragmode='zoom'
-                            )
-                            
-                            # 閰嶇疆鍥捐〃鍙傛暟
-                            config = {
-                                'scrollZoom': True
-                            }
-                            
-                            # 鏄剧ず鍥捐〃
-                            st.plotly_chart(fig, use_container_width=True, config=config)
-               
-                            # 鏄剧ず鏋佸�肩偣鍒嗘瀽
-                            st.subheader("鏋佸�肩偣鍒嗘瀽")
-                            if not extreme_points.empty:
-                                # 鍑嗗灞曠ず鏁版嵁
-                                display_df = extreme_points[['time', 'count_under', 'count_in_range', 'count_over', 'pass_rate']].copy()
-                                
-                                # 鏍煎紡鍖栨椂闂存埑
-                                display_df['time'] = display_df['time'].dt.strftime('%Y-%m-%d %H:%M:%S')
-                                
-                                # 淇敼鍒楀悕
-                                display_df.columns = ['鏃堕棿鎴�', '瓒呬笅闄愭暟鍊�', '鑼冨洿鍐呮暟鍊�', '瓒呬笂闄愭暟鍊�', '鍚堟牸鐜�(%)']
-                                
-                                # 鏄剧ず鏁版嵁琛ㄦ牸
-                                st.dataframe(display_df, use_container_width=True)
-                                
-                                # 鏄剧ず鏋佸�肩偣鏁伴噺
-                                st.info(f"鍏辫瘑鍒埌 {len(extreme_points)} 涓瀬鍊肩偣")
-                                
-                                # 娣诲姞瀵煎嚭鍔熻兘
-                                import csv
-                                import io
-                                
-                                # 鍒涘缓CSV鏁版嵁
-                                csv_buffer = io.StringIO()
-                                display_df.to_csv(csv_buffer, index=False, encoding='utf-8-sig')
-                                csv_data = csv_buffer.getvalue()
-                                
-                                # 娣诲姞涓嬭浇鎸夐挳
-                                st.download_button(
-                                    label="涓嬭浇鏋佸�肩偣鍒嗘瀽缁撴灉",
-                                    data=csv_data,
-                                    file_name=f"鏋佸�肩偣鍒嗘瀽_{start_date}_{end_date}.csv",
-                                    mime="text/csv"
-                                )
-                            else:
-                                st.warning("鏈瘑鍒埌鏋佸�肩偣")
-                        
-                                         
-                            # 鏄剧ず閲嶉噺瓒嬪娍鍥�
-                            st.subheader("閲嶉噺瓒嬪娍鍥�")
-                            if 'weight' in cleaned_data.columns:
-                                # 鍒涘缓閲嶉噺瓒嬪娍鍥�
-                                import plotly.graph_objects as go
-                                
-                                # 鍒涘缓鍥捐〃
-                                weight_fig = go.Figure()
-                                
-                                # 妫�鏌ユ槸鍚﹀寘鍚槇鍊肩浉鍏冲瓧娈�
-                                has_thresholds = all(col in cleaned_data.columns for col in ['baseline_value', 'over_difference', 'under_difference'])
-                                
-                                # 璁$畻鍔ㄦ�侀槇鍊�
-                                if has_thresholds:
-                                    # 澶嶅埗鏁版嵁浠ラ伩鍏嶄慨鏀瑰師濮嬫暟鎹�
-                                    threshold_data = cleaned_data.copy()
-                                    
-                                    # 澶勭悊闆跺��
-                                    for col in ['baseline_value', 'over_difference', 'under_difference']:
-                                        threshold_data[col] = threshold_data[col].replace(0, pd.NA)
-                                    
-                                    # 鍚戝墠濉厖缂哄け鍊�
-                                    threshold_data = threshold_data.ffill()
-                                    
-                                    # 璁$畻涓婁笅闄愰槇鍊�
-                                    threshold_data['upper_threshold'] = threshold_data['over_difference']
-                                    threshold_data['lower_threshold'] = threshold_data['under_difference']
-                                    
-                                    # 鏍囪瓒呭嚭闃堝�肩殑鐐�
-                                    threshold_data['is_out_of_range'] = (threshold_data['weight'] > threshold_data['upper_threshold']) | (threshold_data['weight'] < threshold_data['lower_threshold'])
-                                    
-                                    # 娣诲姞鍩哄噯鍊肩嚎锛堝姩鎬侊級
-                                    weight_fig.add_trace(go.Scatter(
-                                        x=threshold_data['time'],
-                                        y=threshold_data['baseline_value'],
-                                        name='鍩哄噯鍊�',
-                                        line=dict(color='green', width=2),
-                                        opacity=0.7
-                                    ))
-                                    
-                                    # 娣诲姞涓婇檺闃堝�肩嚎锛堝姩鎬侊級
-                                    weight_fig.add_trace(go.Scatter(
-                                        x=threshold_data['time'],
-                                        y=threshold_data['upper_threshold'],
-                                        name='涓婇檺闃堝��',
-                                        line=dict(color='red', width=2),
-                                        opacity=0.7
-                                    ))
-                                    
-                                    # 娣诲姞涓嬮檺闃堝�肩嚎锛堝姩鎬侊級
-                                    weight_fig.add_trace(go.Scatter(
-                                        x=threshold_data['time'],
-                                        y=threshold_data['lower_threshold'],
-                                        name='涓嬮檺闃堝��',
-                                        line=dict(color='orange', width=2),
-                                        opacity=0.7
-                                    ))
-                                    
-                                    # 鍒嗙姝e父鍜屽紓甯告暟鎹偣
-                                    normal_data = threshold_data[~threshold_data['is_out_of_range']]
-                                    out_of_range_data = threshold_data[threshold_data['is_out_of_range']]
-                                    
-                                    # 娣诲姞姝e父閲嶉噺鐐�
-                                    weight_fig.add_trace(go.Scatter(
-                                        x=normal_data['time'],
-                                        y=normal_data['weight'],
-                                        name='閲嶉噺 (姝e父)',
-                                        opacity=0.8,
-                                        mode='markers',
-                                        marker=dict(
-                                            size=4,
-                                            color='blue',
-                                            symbol='circle',
-                                            line=dict(
-                                                width=0,
-                                                color='blue'
-                                            )
-                                        )
-                                    ))
-                                    
-                                    # 娣诲姞寮傚父閲嶉噺鐐�
-                                    if not out_of_range_data.empty:
-                                        weight_fig.add_trace(go.Scatter(
-                                            x=out_of_range_data['time'],
-                                            y=out_of_range_data['weight'],
-                                            name='閲嶉噺 (寮傚父)',
-                                            opacity=0.8,
-                                            mode='markers',
-                                            marker=dict(
-                                                size=4,
-                                                color='red',
-                                                symbol='triangle-up',
-                                                line=dict(
-                                                    width=2,
-                                                    color='darkred'
-                                                )
-                                            )
-                                        ))
-                                else:
-                                    # 娌℃湁闃堝�兼暟鎹紝鍙樉绀洪噸閲忚秼鍔�
-                                    weight_fig.add_trace(go.Scatter(
-                                        x=cleaned_data['time'],
-                                        y=cleaned_data['weight'],
-                                        name='閲嶉噺',
-                                        line=dict(color='blue', width=2),
-                                        opacity=0.8
-                                    ))
-                                    st.warning("鏁版嵁涓笉鍖呭惈闃堝�肩浉鍏冲瓧娈碉紝鏃犳硶鏄剧ず闃堝�肩嚎鍜屽紓甯歌绀猴紒")
-                                
-                                # 閰嶇疆鍥捐〃甯冨眬
-                                weight_fig.update_layout(
-                                    title='閲嶉噺闅忔椂闂村彉鍖栬秼鍔�',
-                                    xaxis_title='鏃堕棿',
-                                    yaxis_title='閲嶉噺',
-                                    xaxis=dict(
-                                        rangeslider=dict(
-                                            visible=True
-                                        ),
-                                        type='date',
-                                        fixedrange=False
-                                    ),
-                                    yaxis=dict(
-                                        fixedrange=False
-                                    ),
-                                    legend=dict(
-                                        orientation="h",
-                                        yanchor="bottom",
-                                        y=1.02,
-                                        xanchor="right",
-                                        x=1
-                                    ),
-                                    hovermode='x unified',
-                                    height=600,
-                                    dragmode='zoom',
-                                    # 娣诲姞鑷畾涔夊伐鍏锋爮鎸夐挳
-                                    updatemenus=[
-                                        dict(
-                                            type="buttons",
-                                            direction="left",
-                                            buttons=list([
-                                                dict(
-                                                    args=["visible", [True, True, True, True, True]],
-                                                    label="鏄剧ず鍏ㄩ儴",
-                                                    method="restyle"
-                                                ),
-                                                dict(
-                                                    args=["visible", [False, False, False, True, True]],
-                                                    label="浠呮樉绀洪噸閲�",
-                                                    method="restyle"
-                                                ),
-                                                dict(
-                                                    args=["visible", [True, True, True, False, False]],
-                                                    label="浠呮樉绀洪槇鍊�",
-                                                    method="restyle"
-                                                ),
-                                                 dict(
-                                                    args=["visible", [True, True, True, True, False]],
-                                                    label="鏄剧ず姝e父閲嶉噺",
-                                                    method="restyle"
-                                                ),
-                                                 dict(
-                                                    args=["visible", [True, True, True, False, True]],
-                                                    label="鏄剧ず寮傚父閲嶉噺",
-                                                    method="restyle"
-                                                )
-                                            ]),
-                                            pad={"r": 10, "t": 10},
-                                            showactive=True,
-                                            x=0.1,
-                                            xanchor="left",
-                                            y=1.1,
-                                            yanchor="top"
-                                        ),
-                                    ]
-                                )
-                                
-                                # 閰嶇疆鍥捐〃鍙傛暟
-                                config = {
-                                    'scrollZoom': True,
-                                    'toImageButtonOptions': {
-                                        'format': 'png',
-                                        'filename': '閲嶉噺瓒嬪娍鍥�',
-                                        'height': 600,
-                                        'width': 1000,
-                                        'scale': 1
-                                    }
-                                }
-                                
-                                # 鏄剧ず鍥捐〃
-                                st.plotly_chart(weight_fig, use_container_width=True, config=config)
-                            
-                            
-                            # 鏄剧ず鏁版嵁琛ㄦ牸
-                            st.subheader("鍘熷鏁版嵁")
-                            st.dataframe(cleaned_data, use_container_width=True)
-                            
-                            # 鏄剧ず璇︾粏缁熻淇℃伅
-                            if stats:
-                                st.subheader("璇︾粏缁熻淇℃伅")
-                                with st.expander("鏌ョ湅璇︾粏缁熻"):
-                                    col_stats1, col_stats2, col_stats3 = st.columns(3)
-                                    
-                                    with col_stats1:
-                                        st.write("**浣庝簬鏍囧噯**")
-                                        st.write(f"骞冲潎鍊�: {round(stats['count_under']['mean'], 2)}")
-                                        st.write(f"鎬诲拰: {stats['count_under']['sum']}")
-                                        st.write(f"鏈�澶у��: {stats['count_under']['max']}")
-                                        st.write(f"鏈�灏忓��: {stats['count_under']['min']}")
-                                    
-                                    with col_stats2:
-                                        st.write("**鍦ㄦ爣鍑嗚寖鍥村唴**")
-                                        st.write(f"骞冲潎鍊�: {round(stats['count_in_range']['mean'], 2)}")
-                                        st.write(f"鎬诲拰: {stats['count_in_range']['sum']}")
-                                        st.write(f"鏈�澶у��: {stats['count_in_range']['max']}")
-                                        st.write(f"鏈�灏忓��: {stats['count_in_range']['min']}")
-                                    
-                                    with col_stats3:
-                                        st.write("**楂樹簬鏍囧噯**")
-                                        st.write(f"骞冲潎鍊�: {round(stats['count_over']['mean'], 2)}")
-                                        st.write(f"鎬诲拰: {stats['count_over']['sum']}")
-                                        st.write(f"鏈�澶у��: {stats['count_over']['max']}")
-                                        st.write(f"鏈�灏忓��: {stats['count_over']['min']}")
+# 瀵艰埅閰嶇疆
+pg = st.navigation({
+    "缁煎悎鍒嗘瀽": [comprehensive_page],
+    "鍒嗛」鍒嗘瀽": [sorting_page, extruder_page, main_process_page]
+})
 
-    # 鏁版嵁搴撹繛鎺ョ姸鎬�
-    st.sidebar.subheader("鏁版嵁搴撶姸鎬�")
-    if 'query_service' in locals() and query_service.db.is_connected():
-        st.sidebar.success("鏁版嵁搴撹繛鎺ユ甯�")
-    else:
-        st.sidebar.warning("鏁版嵁搴撴湭杩炴帴")
+# 杩愯瀵艰埅
+pg.run()
 
-elif menu == "鎸ゅ嚭鏈�":
-    # 鍒濆鍖栨湇鍔�
-    extruder_service = ExtruderService()
-    processing_service = DataProcessingService()
-
-    # 椤甸潰鏍囬
-    st.title("鎸ゅ嚭鏈烘暟鎹垎鏋�")
-
-    # 鏌ヨ鏉′欢鍖哄煙
-    st.subheader("鏌ヨ閰嶇疆")
-    col1, col2, col3 = st.columns([2, 2, 1])
-    
-    with col1:
-        start_date = st.date_input("寮�濮嬫棩鏈�", datetime.now() - timedelta(days=7), key="extruder_start_date")
-    
-    with col2:
-        end_date = st.date_input("缁撴潫鏃ユ湡", datetime.now(), key="extruder_end_date")
-    
-    with col3:
-        st.write("")  # 鍗犱綅
-        query_button = st.button("鏌ヨ鏁版嵁", key="extruder_query")
-
-    # 杞崲涓篸atetime瀵硅薄锛堝寘鍚椂闂达級
-    start_datetime = datetime.combine(start_date, datetime.min.time())
-    end_datetime = datetime.combine(end_date, datetime.max.time())
-
-    # 鏌ヨ鎸夐挳澶勭悊
-    if query_button:
-                # 楠岃瘉鏃ユ湡鑼冨洿
-                if start_datetime > end_datetime:
-                    st.error("寮�濮嬫棩鏈熶笉鑳芥櫄浜庣粨鏉熸棩鏈燂紒")
-                else:
-                    # 鏄剧ず鍔犺浇鐘舵��
-                    with st.spinner("姝e湪鏌ヨ鏁版嵁..."):
-                        # 鏌ヨ鏁版嵁
-                        raw_data = extruder_service.get_extruder_data(start_datetime, end_datetime)
-                        
-                        if raw_data is None or raw_data.empty:
-                            st.warning("鏈煡璇㈠埌鏁版嵁锛岃妫�鏌ユ棩鏈熻寖鍥存垨鏁版嵁搴撹繛鎺ワ紒")
-                            st.session_state['extruder_results'] = None
-                        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)
-                            
-                            
-                            # 缂撳瓨缁撴灉
-                            st.session_state['extruder_results'] = {
-                                'cleaned_data': cleaned_data,
-                                'batch_changes': batch_changes,
-                               # 'trends': trends,
-                            }
-                            
-                            # 鏄剧ず鏁版嵁姒傝
-                            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()}")
-                            
-                                                        # 鏄剧ず鎹㈡壒鍒嗘瀽
-                            st.subheader("鎹㈡壒鍒嗘瀽")
-                            if not batch_changes.empty:
-                                # 鍑嗗灞曠ず鏁版嵁
-                                batch_display = batch_changes[['batch_id', 'compound_code', 'start_time', 'end_time', 'duration_minutes']].copy()
-                                
-                                # 鏍煎紡鍖栨椂闂�
-                                batch_display['start_time'] = batch_display['start_time'].dt.strftime('%Y-%m-%d %H:%M:%S')
-                                batch_display['end_time'] = batch_display['end_time'].dt.strftime('%Y-%m-%d %H:%M:%S')
-                                
-                                # 淇敼鍒楀悕
-                                batch_display.columns = ['鎵瑰彿', '鑳舵枡鍙�', '寮�濮嬫椂闂�', '缁撴潫鏃堕棿', '鎸佺画鏃堕暱(鍒嗛挓)']                                
-                                # 鏄剧ず鏁版嵁琛ㄦ牸
-                                st.dataframe(batch_display, use_container_width=True)
-                            else:
-                                st.warning("鏈娴嬪埌鎹㈡壒浜嬩欢")
-                            
-                            # 鏄剧ず鎹㈡枡鎿嶄綔鍙鍖栧浘琛�
-                            st.subheader("鎹㈡枡鎿嶄綔鍙鍖�")
-                            if not batch_changes.empty:
-                                # 鍒涘缓鎹㈡枡鎿嶄綔鍙鍖栧浘琛�
-                                import plotly.graph_objects as go
-                                
-                                # 鍑嗗鍥捐〃鏁版嵁
-                                fig = go.Figure()
-                                
-                                # 娣诲姞鍏抽敭鍙傛暟瓒嬪娍绾�
-                                fig.add_trace(go.Scatter(
-                                    x=cleaned_data['time'],
-                                    y=cleaned_data['screw_speed_actual'],
-                                    name='瀹為檯杞��',
-                                    line=dict(color='blue', width=2),
-                                    opacity=0.8
-                                ))
-                                
-                                fig.add_trace(go.Scatter(
-                                    x=cleaned_data['time'],
-                                    y=cleaned_data['head_pressure'],
-                                    name='鏈哄ご鍘嬪姏',
-                                    line=dict(color='red', width=2),
-                                    opacity=0.8,
-                                    yaxis='y2'
-                                ))
-                                
-                                fig.add_trace(go.Scatter(
-                                    x=cleaned_data['time'],
-                                    y=cleaned_data['extruder_current'],
-                                    name='鎸ゅ嚭鏈虹數娴�',
-                                    line=dict(color='green', width=2),
-                                    opacity=0.8,
-                                    yaxis='y3'
-                                ))
-                                
-                                fig.add_trace(go.Scatter(
-                                    x=cleaned_data['time'],
-                                    y=cleaned_data['metered_weight'],
-                                    name='绫抽噸',
-                                    line=dict(color='orange', width=2),
-                                    opacity=0.8,
-                                    yaxis='y4'
-                                ))
-                                
-                                # 娣诲姞鎹㈡枡浜嬩欢鏍囪
-                                for i, row in batch_changes.iterrows():
-                                    # 娣诲姞鍨傜洿绾�
-                                    fig.add_shape(
-                                        type="line",
-                                        x0=row['start_time'],
-                                        y0=0,
-                                        x1=row['start_time'],
-                                        y1=1,
-                                        yref="paper",
-                                        line=dict(
-                                            color="purple",
-                                            width=2,
-                                            dash="dash"
-                                        )
-                                    )
-                                    
-                                    # 娣诲姞娉ㄩ噴
-                                    fig.add_annotation(
-                                        x=row['start_time'],
-                                        y=1,
-                                        yref='paper',
-                                        text=f'鎹㈡枡: {row["compound_code"]}\n鎵瑰彿: {row["batch_id"]}',
-                                        showarrow=True,
-                                        arrowhead=1,
-                                        ax=0,
-                                        ay=-60
-                                    )
-                                
-                                # 閰嶇疆鍥捐〃甯冨眬
-                                fig.update_layout(
-                                    title='鎹㈡枡鎿嶄綔鍏抽敭鍙傛暟鍙樺寲瓒嬪娍',
-                                    xaxis_title='鏃堕棿',
-                                    xaxis=dict(
-                                        rangeslider=dict(
-                                            visible=True
-                                        ),
-                                        type='date'
-                                    ),
-                                    yaxis_title='瀹為檯杞�� (rpm)',
-                                    yaxis2=dict(
-                                        title='鏈哄ご鍘嬪姏 (MPa)',
-                                        overlaying='y',
-                                        side='right',
-                                        position=0.85
-                                    ),
-                                    yaxis3=dict(
-                                        title='鎸ゅ嚭鏈虹數娴� (A)',
-                                        overlaying='y',
-                                        side='right',
-                                        position=0.92
-                                    ),
-                                    yaxis4=dict(
-                                        title='绫抽噸 (kg)',
-                                        overlaying='y',
-                                        side='right',
-                                        position=1
-                                    ),
-                                    legend=dict(
-                                        orientation="h",
-                                        yanchor="bottom",
-                                        y=1.02,
-                                        xanchor="right",
-                                        x=1
-                                    ),
-                                    hovermode='x unified',
-                                    height=700
-                                )
-                                
-                                # 鏄剧ず鍥捐〃
-                                st.plotly_chart(fig, use_container_width=True)
-                                
-                                # 娣诲姞鏁版嵁瀵煎嚭鍔熻兘
-                                import csv
-                                import io
-                                import pandas as pd
-                                
-                                # 鍑嗗瀵煎嚭鏁版嵁
-                                export_data = []
-                                for i, row in batch_changes.iterrows():
-                                    # 鑾峰彇鎹㈡枡鍓嶅悗鐨勬暟鎹�
-                                    before_change = cleaned_data[cleaned_data['time'] < row['start_time']].tail(5)
-                                    after_change = cleaned_data[cleaned_data['time'] >= row['start_time']].head(5)
-                                    
-                                    # 娣诲姞鎹㈡枡浜嬩欢璁板綍
-                                    export_data.append({
-                                        'event_type': '鎹㈡枡浜嬩欢',
-                                        'batch_id': row['batch_id'],
-                                        'compound_code': row['compound_code'],
-                                        'time': row['start_time'],
-                                        'screw_speed': '',
-                                        'head_pressure': '',
-                                        'extruder_current': '',
-                                        'metered_weight': ''
-                                    })
-                                    
-                                    # 娣诲姞鎹㈡枡鍓嶆暟鎹�
-                                    for _, before_row in before_change.iterrows():
-                                        export_data.append({
-                                            'event_type': '鎹㈡枡鍓�',
-                                            'batch_id': row['batch_id'],
-                                            'compound_code': row['compound_code'],
-                                            'time': before_row['time'],
-                                            'screw_speed': before_row['screw_speed_actual'],
-                                            'head_pressure': before_row['head_pressure'],
-                                            'extruder_current': before_row['extruder_current'],
-                                            'metered_weight': before_row['metered_weight']
-                                        })
-                                    
-                                    # 娣诲姞鎹㈡枡鍚庢暟鎹�
-                                    for _, after_row in after_change.iterrows():
-                                        export_data.append({
-                                            'event_type': '鎹㈡枡鍚�',
-                                            'batch_id': row['batch_id'],
-                                            'compound_code': row['compound_code'],
-                                            'time': after_row['time'],
-                                            'screw_speed': after_row['screw_speed_actual'],
-                                            'head_pressure': after_row['head_pressure'],
-                                            'extruder_current': after_row['extruder_current'],
-                                            'metered_weight': after_row['metered_weight']
-                                        })
-                                
-                                # 杞崲涓篋ataFrame
-                                export_df = pd.DataFrame(export_data)
-                                
-                                # 鍒涘缓CSV鏁版嵁
-                                csv_buffer = io.StringIO()
-                                export_df.to_csv(csv_buffer, index=False, encoding='utf-8-sig')
-                                csv_data = csv_buffer.getvalue()
-                                
-                                # 娣诲姞涓嬭浇鎸夐挳
-                                st.download_button(
-                                    label="涓嬭浇鎹㈡枡鎿嶄綔鍒嗘瀽鏁版嵁",
-                                    data=csv_data,
-                                    file_name=f"鎹㈡枡鎿嶄綔鍒嗘瀽_{start_date}_{end_date}.csv",
-                                    mime="text/csv"
-                                )
-                            else:
-                                st.warning("鏈娴嬪埌鎹㈡壒浜嬩欢锛屾棤娉曠敓鎴愭崲鏂欐搷浣滃浘琛�")
-                            
-                            # 鏄剧ず鍘熷鏁版嵁
-                            st.subheader("鍘熷鏁版嵁")
-                            st.dataframe(cleaned_data, use_container_width=True)
-
-    # 鏁版嵁搴撹繛鎺ョ姸鎬�
-    st.sidebar.subheader("鏁版嵁搴撶姸鎬�")
-    if 'extruder_service' in locals() and extruder_service.db.is_connected():
-        st.sidebar.success("鏁版嵁搴撹繛鎺ユ甯�")
-    else:
-        st.sidebar.warning("鏁版嵁搴撴湭杩炴帴")
-
-# 椤佃剼
-st.sidebar.markdown("---")
-st.sidebar.markdown("漏 2026 鏁版嵁鍒嗘瀽绯荤粺")
-
-# 缂撳瓨娓呯悊鏈哄埗
-def clear_cache():
-    """娓呯悊浼氳瘽缂撳瓨锛屽綋鍒囨崲鑿滃崟鎴栨洿鏂版煡璇㈡潯浠舵椂璋冪敤"""
-    if 'query_results' in st.session_state:
-        del st.session_state['query_results']
-    if 'extruder_results' in st.session_state:
-        del st.session_state['extruder_results']
-
-# 鍒濆鍖栦細璇濈姸鎬�
-if 'query_results' not in st.session_state:
-    st.session_state['query_results'] = None
-if 'extruder_results' not in st.session_state:
-    st.session_state['extruder_results'] = None
-
-# 鐩戝惉鑿滃崟鍒囨崲锛屾竻鐞嗙紦瀛�
-if 'previous_menu' not in st.session_state:
-    st.session_state['previous_menu'] = menu
-elif st.session_state['previous_menu'] != menu:
-    clear_cache()
-    st.session_state['previous_menu'] = menu
-
-# 鍏抽棴鏁版嵁搴撹繛鎺ワ紙褰撳簲鐢ㄧ粨鏉熸椂锛�
-def on_app_close():
-    if 'query_service' in locals():
-        query_service.close_connection()
-    if 'extruder_service' in locals():
-        extruder_service.close_connection()
-
-# 娉ㄥ唽搴旂敤鍏抽棴鍥炶皟
-st.session_state['app_close'] = on_app_close
\ No newline at end of file
+# 鏄剧ず椤佃剼
+show_footer()

--
Gitblit v1.9.3