diff --git a/app.py b/app.py index c54447d..8061c6c 100644 --- a/app.py +++ b/app.py @@ -5,14 +5,11 @@ import streamlit as st import numpy as np -import pandas as pd import plotly.graph_objects as go -import plotly.express as px -from plotly.subplots import make_subplots # ─── Page Config ──────────────────────────────────────────────────────────── st.set_page_config( - page_title="农业智能决策系统", + page_title="种植决策助手", page_icon="🌾", layout="wide", initial_sidebar_state="expanded", @@ -22,166 +19,175 @@ st.set_page_config( st.markdown(""" """, unsafe_allow_html=True) @@ -194,42 +200,42 @@ CROPS = { "optimal": {"ph": (6.0, 7.0), "N": (80, 120), "P": (30, 60), "K": (40, 80), "rainfall": (150, 250), "temp": (22, 30)}, "base_yield": 7500, # kg/ha - "color": "#4ade80" + "color": "#4a7c59" }, "小麦": { "emoji": "🌿", "optimal": {"ph": (6.0, 7.5), "N": (60, 100), "P": (20, 50), "K": (30, 60), "rainfall": (60, 120), "temp": (15, 22)}, "base_yield": 6000, - "color": "#f59e0b" + "color": "#c69c5d" }, "玉米": { "emoji": "🌽", "optimal": {"ph": (5.8, 7.0), "N": (100, 150), "P": (40, 70), "K": (60, 100), "rainfall": (100, 180), "temp": (20, 28)}, "base_yield": 8500, - "color": "#fbbf24" + "color": "#e8a93f" }, "大豆": { "emoji": "🫘", "optimal": {"ph": (6.0, 7.0), "N": (20, 50), "P": (30, 60), "K": (40, 80), "rainfall": (80, 150), "temp": (18, 26)}, "base_yield": 3500, - "color": "#a78bfa" + "color": "#8b7cb3" }, "油菜": { "emoji": "🌻", "optimal": {"ph": (6.0, 7.5), "N": (80, 130), "P": (30, 60), "K": (50, 90), "rainfall": (80, 130), "temp": (15, 20)}, "base_yield": 3000, - "color": "#f97316" + "color": "#d97836" }, "棉花": { "emoji": "☁️", "optimal": {"ph": (6.0, 8.0), "N": (60, 100), "P": (20, 45), "K": (40, 70), "rainfall": (70, 120), "temp": (25, 32)}, "base_yield": 4500, - "color": "#e2e8f0" + "color": "#5a6b7c" }, } @@ -294,11 +300,11 @@ def rank_crops(ph, N, P, K, rainfall, temp, pesticide, area): # ─── Sidebar Inputs ────────────────────────────────────────────────────────── with st.sidebar: - st.markdown('
🌾 农业决策
', unsafe_allow_html=True) - st.markdown('
SMART FARMING SYSTEM v2.0
', unsafe_allow_html=True) - st.markdown("---") + st.markdown('', unsafe_allow_html=True) + st.markdown('', unsafe_allow_html=True) + st.markdown("
", unsafe_allow_html=True) - st.markdown('
🧪 土壤参数
', unsafe_allow_html=True) + st.markdown('
🧪 土壤参数
', unsafe_allow_html=True) col1, col2 = st.columns(2) with col1: ph = st.slider("pH 值", 4.0, 9.0, 6.5, 0.1) @@ -334,10 +340,10 @@ best_crop = rankings[0] # ─── Main Layout ───────────────────────────────────────────────────────────── st.markdown(f""" -
-
农业智能决策系统
+
+
种植决策助手
-
YIELD = f(SOIL · WEATHER · PESTICIDE)  |  基于多因子 Cobb-Douglas 产量模型
+
输入土壤与气象条件,获得作物产量预测与种植建议
""", unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) @@ -392,14 +398,14 @@ with col_left: r=factor_vals_closed, theta=factor_names_closed, fill='toself', - fillcolor='rgba(74,222,128,0.15)', - line=dict(color='#4ade80', width=2), + fillcolor='rgba(74, 124, 89, 0.15)', + line=dict(color='#4a7c59', width=2), name=selected_crop, )) fig_radar.add_trace(go.Scatterpolar( r=[100]*len(factor_names_closed), theta=factor_names_closed, - line=dict(color='rgba(255,255,255,0.1)', width=1, dash='dot'), + line=dict(color='rgba(0,0,0,0.15)', width=1, dash='dot'), mode='lines', name='理想值', )) @@ -407,14 +413,14 @@ with col_left: polar=dict( bgcolor='rgba(0,0,0,0)', radialaxis=dict(range=[0, 100], showticklabels=True, - tickfont=dict(color='#64748b', size=9), - gridcolor='rgba(255,255,255,0.06)'), - angularaxis=dict(tickfont=dict(color='#e2e8f0', size=11), - gridcolor='rgba(255,255,255,0.08)'), + tickfont=dict(color='#5a5a5a', size=9), + gridcolor='rgba(0,0,0,0.08)'), + angularaxis=dict(tickfont=dict(color='#2c2c2c', size=11), + gridcolor='rgba(0,0,0,0.1)'), ), paper_bgcolor='rgba(0,0,0,0)', plot_bgcolor='rgba(0,0,0,0)', - font=dict(color='#e2e8f0'), + font=dict(color='#2c2c2c'), legend=dict(orientation='h', y=-0.12, font=dict(size=10)), margin=dict(t=20, b=40, l=40, r=40), height=320, @@ -436,11 +442,11 @@ with col_right:
{r['score']*100:.1f}% -
+
-
- {r['yield_ha']:,.0f} kg/ha  ·  总产 {r['total_yield']/1000:,.1f} 吨 +
+ {r['yield_ha']:,.0f} kg/ha · 总产 {r['total_yield']/1000:,.1f} 吨
""", unsafe_allow_html=True) @@ -456,18 +462,18 @@ with sa_col1: fig_N = go.Figure() fig_N.add_trace(go.Scatter( x=N_range, y=y_N, - mode='lines', line=dict(color='#4ade80', width=2.5), - fill='tozeroy', fillcolor='rgba(74,222,128,0.08)', + mode='lines', line=dict(color='#4a7c59', width=2.5), + fill='tozeroy', fillcolor='rgba(74, 124, 89, 0.08)', name='产量' )) - fig_N.add_vline(x=N, line=dict(color='#f59e0b', width=1.5, dash='dot'), - annotation_text=f"当前 {N}", annotation_font_color='#f59e0b') + fig_N.add_vline(x=N, line=dict(color='#d4a574', width=1.5, dash='dot'), + annotation_text=f"当前 {N}", annotation_font_color='#7c5e42') fig_N.update_layout( - title=dict(text="氮肥用量 vs 产量", font=dict(color='#94a3b8', size=12)), - xaxis=dict(title="氮 N (mg/kg)", color='#64748b', gridcolor='rgba(255,255,255,0.05)'), - yaxis=dict(title="产量 (kg/ha)", color='#64748b', gridcolor='rgba(255,255,255,0.05)'), + title=dict(text="氮肥用量 vs 产量", font=dict(color='#5a5a5a', size=12)), + xaxis=dict(title="氮 N (mg/kg)", color='#5a5a5a', gridcolor='rgba(0,0,0,0.06)'), + yaxis=dict(title="产量 (kg/ha)", color='#5a5a5a', gridcolor='rgba(0,0,0,0.06)'), paper_bgcolor='rgba(0,0,0,0)', plot_bgcolor='rgba(0,0,0,0)', - font=dict(color='#e2e8f0', size=10), + font=dict(color='#2c2c2c', size=10), margin=dict(t=36, b=36, l=50, r=20), height=220, showlegend=False, ) @@ -480,18 +486,18 @@ with sa_col2: fig_R = go.Figure() fig_R.add_trace(go.Scatter( x=rain_range, y=y_rain, - mode='lines', line=dict(color='#38bdf8', width=2.5), - fill='tozeroy', fillcolor='rgba(56,189,248,0.08)', + mode='lines', line=dict(color='#5a8f9e', width=2.5), + fill='tozeroy', fillcolor='rgba(90, 143, 158, 0.08)', name='产量' )) - fig_R.add_vline(x=rainfall, line=dict(color='#f59e0b', width=1.5, dash='dot'), - annotation_text=f"当前 {rainfall}mm", annotation_font_color='#f59e0b') + fig_R.add_vline(x=rainfall, line=dict(color='#d4a574', width=1.5, dash='dot'), + annotation_text=f"当前 {rainfall}mm", annotation_font_color='#7c5e42') fig_R.update_layout( - title=dict(text="月降雨量 vs 产量", font=dict(color='#94a3b8', size=12)), - xaxis=dict(title="降雨量 (mm/月)", color='#64748b', gridcolor='rgba(255,255,255,0.05)'), - yaxis=dict(title="产量 (kg/ha)", color='#64748b', gridcolor='rgba(255,255,255,0.05)'), + title=dict(text="月降雨量 vs 产量", font=dict(color='#5a5a5a', size=12)), + xaxis=dict(title="降雨量 (mm/月)", color='#5a5a5a', gridcolor='rgba(0,0,0,0.06)'), + yaxis=dict(title="产量 (kg/ha)", color='#5a5a5a', gridcolor='rgba(0,0,0,0.06)'), paper_bgcolor='rgba(0,0,0,0)', plot_bgcolor='rgba(0,0,0,0)', - font=dict(color='#e2e8f0', size=10), + font=dict(color='#2c2c2c', size=10), margin=dict(t=36, b=36, l=50, r=20), height=220, showlegend=False, ) @@ -508,23 +514,23 @@ fig_bar = go.Figure() fig_bar.add_trace(go.Bar( x=crop_names, y=crop_yields, marker=dict(color=crop_colors, opacity=0.85, - line=dict(color='rgba(255,255,255,0.2)', width=1)), + line=dict(color='rgba(0,0,0,0.08)', width=1)), text=[f"{y:,.0f}" for y in crop_yields], textposition='outside', - textfont=dict(color='#94a3b8', size=10, family='JetBrains Mono'), + textfont=dict(color='#5a5a5a', size=10), )) fig_bar.update_layout( - xaxis=dict(color='#64748b', gridcolor='rgba(255,255,255,0.04)'), - yaxis=dict(title="预期产量 (kg/ha)", color='#64748b', gridcolor='rgba(255,255,255,0.05)'), + xaxis=dict(color='#5a5a5a', gridcolor='rgba(0,0,0,0.04)'), + yaxis=dict(title="预期产量 (kg/ha)", color='#5a5a5a', gridcolor='rgba(0,0,0,0.06)'), paper_bgcolor='rgba(0,0,0,0)', plot_bgcolor='rgba(0,0,0,0)', - font=dict(color='#e2e8f0', size=11), - margin=dict(t=20, b=30, l=60, r=20), height=240, + font=dict(color='#2c2c2c', size=11), + margin=dict(t=20, b=30, l=60, r=20), height=260, showlegend=False, ) st.plotly_chart(fig_bar, use_container_width=True) # ─── Advisory Panel ─────────────────────────────────────────────────────────── -st.markdown('
💡 智能建议
', unsafe_allow_html=True) +st.markdown('
💡 种植建议
', unsafe_allow_html=True) adv1, adv2 = st.columns(2) with adv1: @@ -557,7 +563,7 @@ with adv1: with adv2: st.markdown(f"""
-
+
当前环境参数下适宜种植:
""", unsafe_allow_html=True) @@ -568,18 +574,17 @@ with adv2: st.markdown(f'{badges}
', unsafe_allow_html=True) st.markdown(f""" -
- 最优方案:{best_crop['emoji']} {best_crop['crop']}
- 预期单产:{best_crop['yield_ha']:,.0f} kg/ha
- {area:.0f}公顷总产:{best_crop['total_yield']/1000:,.1f} 吨 +
+ 最优方案:{best_crop['emoji']} {best_crop['crop']}
+ 预期单产:{best_crop['yield_ha']:,.0f} kg/ha
+ {area:.0f}公顷总产:{best_crop['total_yield']/1000:,.1f} 吨
""", unsafe_allow_html=True) # ─── Footer ─────────────────────────────────────────────────────────────────── st.markdown("
", unsafe_allow_html=True) st.markdown(""" -
- YIELD = f(Soil, Weather, Pesticide)  |  Cobb-Douglas Multi-Factor Model  |  农业智能决策系统 +
+ 种植决策助手 · 基于 Cobb-Douglas 多因子产量模型 · 仅供参考
""", unsafe_allow_html=True)