Update src/streamlit_app.py
Browse files- src/streamlit_app.py +263 -123
src/streamlit_app.py
CHANGED
|
@@ -2,98 +2,208 @@ import streamlit as st
|
|
| 2 |
import pandas as pd
|
| 3 |
import math
|
| 4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
# 配置页面
|
| 6 |
st.set_page_config(
|
| 7 |
-
page_title="
|
| 8 |
page_icon="🧪",
|
| 9 |
layout="wide"
|
| 10 |
)
|
| 11 |
|
| 12 |
# 页面标题
|
| 13 |
-
st.title("
|
| 14 |
st.markdown("---")
|
| 15 |
|
| 16 |
-
# 常见溶剂的摩尔质量和密度数据库
|
| 17 |
-
SOLVENTS_DB = {
|
| 18 |
-
"水": {"M": 18.02, "density": 1.000},
|
| 19 |
-
"乙醇": {"M": 46.07, "density": 0.789},
|
| 20 |
-
"甲醇": {"M": 32.04, "density": 0.792},
|
| 21 |
-
"异丙醇": {"M": 60.10, "density": 0.786},
|
| 22 |
-
"丙酮": {"M": 58.08, "density": 0.784},
|
| 23 |
-
"乙酸乙酯": {"M": 88.11, "density": 0.902},
|
| 24 |
-
"甲苯": {"M": 92.14, "density": 0.867},
|
| 25 |
-
"二氯甲烷": {"M": 84.93, "density": 1.326},
|
| 26 |
-
"氯仿": {"M": 119.38, "density": 1.489},
|
| 27 |
-
"四氢呋喃": {"M": 72.11, "density": 0.889},
|
| 28 |
-
"二甲基亚砜": {"M": 78.13, "density": 1.100},
|
| 29 |
-
"N,N-二甲基甲酰胺": {"M": 73.09, "density": 0.944},
|
| 30 |
-
"乙腈": {"M": 41.05, "density": 0.786},
|
| 31 |
-
"正己烷": {"M": 86.18, "density": 0.659},
|
| 32 |
-
"环己烷": {"M": 84.16, "density": 0.779},
|
| 33 |
-
"苯": {"M": 78.11, "density": 0.876},
|
| 34 |
-
"乙二醇": {"M": 62.07, "density": 1.113},
|
| 35 |
-
"甘油": {"M": 92.09, "density": 1.261}
|
| 36 |
-
}
|
| 37 |
-
|
| 38 |
# 侧边栏 - 转换模式选择
|
| 39 |
-
st.sidebar.header("
|
| 40 |
conversion_mode = st.sidebar.radio(
|
| 41 |
-
"
|
| 42 |
-
["
|
| 43 |
)
|
| 44 |
|
| 45 |
# 溶剂选择
|
| 46 |
-
st.sidebar.header("
|
| 47 |
-
st.sidebar.write("
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
|
| 49 |
# 溶剂A选择
|
| 50 |
-
solvent_a_name = st.sidebar.selectbox("
|
| 51 |
|
| 52 |
-
if solvent_a_name == "
|
| 53 |
col1, col2 = st.sidebar.columns(2)
|
| 54 |
with col1:
|
| 55 |
-
M_a = st.number_input("
|
| 56 |
with col2:
|
| 57 |
-
rho_a = st.number_input("
|
| 58 |
else:
|
| 59 |
-
M_a =
|
| 60 |
-
rho_a =
|
| 61 |
-
st.sidebar.write(f"
|
| 62 |
-
st.sidebar.write(f"
|
| 63 |
|
| 64 |
# 溶剂B选择
|
| 65 |
-
solvent_b_name = st.sidebar.selectbox("
|
| 66 |
|
| 67 |
-
if solvent_b_name == "
|
| 68 |
col1, col2 = st.sidebar.columns(2)
|
| 69 |
with col1:
|
| 70 |
-
M_b = st.number_input("
|
| 71 |
with col2:
|
| 72 |
-
rho_b = st.number_input("
|
| 73 |
else:
|
| 74 |
-
M_b =
|
| 75 |
-
rho_b =
|
| 76 |
-
st.sidebar.write(f"
|
| 77 |
-
st.sidebar.write(f"
|
| 78 |
|
| 79 |
# 主界面内容
|
| 80 |
col1, col2 = st.columns(2)
|
| 81 |
|
| 82 |
-
if conversion_mode == "
|
| 83 |
with col1:
|
| 84 |
-
st.header("
|
| 85 |
-
x_a = st.
|
| 86 |
-
f"{solvent_a_name}
|
| 87 |
min_value=0.0,
|
| 88 |
max_value=1.0,
|
| 89 |
value=0.5,
|
| 90 |
-
step=0.
|
|
|
|
| 91 |
)
|
| 92 |
x_b = 1.0 - x_a
|
| 93 |
-
st.write(f"{solvent_b_name}
|
| 94 |
|
| 95 |
# 计算体积分数
|
| 96 |
-
# V_A/V_total = (x_A * M_A / rho_A) / (x_A * M_A / rho_A + x_B * M_B / rho_B)
|
| 97 |
V_ratio_a = x_a * M_a / rho_a
|
| 98 |
V_ratio_b = x_b * M_b / rho_b
|
| 99 |
V_total = V_ratio_a + V_ratio_b
|
|
@@ -105,28 +215,28 @@ if conversion_mode == "摩尔分数 → 体积分数":
|
|
| 105 |
phi_a = phi_b = 0
|
| 106 |
|
| 107 |
with col2:
|
| 108 |
-
st.header("
|
| 109 |
-
st.metric(f"{solvent_a_name}
|
| 110 |
-
st.metric(f"{solvent_b_name}
|
| 111 |
|
| 112 |
# 验证
|
| 113 |
-
st.write(f"
|
| 114 |
|
| 115 |
else: # 体积分数 → 摩尔分数
|
| 116 |
with col1:
|
| 117 |
-
st.header("
|
| 118 |
-
phi_a = st.
|
| 119 |
-
f"{solvent_a_name}
|
| 120 |
min_value=0.0,
|
| 121 |
max_value=1.0,
|
| 122 |
value=0.5,
|
| 123 |
-
step=0.
|
|
|
|
| 124 |
)
|
| 125 |
phi_b = 1.0 - phi_a
|
| 126 |
-
st.write(f"{solvent_b_name}
|
| 127 |
|
| 128 |
# 计算摩尔分数
|
| 129 |
-
# x_A = (phi_A * rho_A / M_A) / (phi_A * rho_A / M_A + phi_B * rho_B / M_B)
|
| 130 |
n_ratio_a = phi_a * rho_a / M_a
|
| 131 |
n_ratio_b = phi_b * rho_b / M_b
|
| 132 |
n_total = n_ratio_a + n_ratio_b
|
|
@@ -138,101 +248,131 @@ else: # 体积分数 → 摩尔分数
|
|
| 138 |
x_a = x_b = 0
|
| 139 |
|
| 140 |
with col2:
|
| 141 |
-
st.header("
|
| 142 |
-
st.metric(f"{solvent_a_name}
|
| 143 |
-
st.metric(f"{solvent_b_name}
|
| 144 |
|
| 145 |
# 验证
|
| 146 |
-
st.write(f"
|
| 147 |
-
|
| 148 |
# 详细信息展示
|
| 149 |
st.markdown("---")
|
| 150 |
-
st.header("
|
| 151 |
|
| 152 |
col1, col2, col3 = st.columns(3)
|
| 153 |
|
| 154 |
with col1:
|
| 155 |
-
st.subheader("
|
| 156 |
df_params = pd.DataFrame({
|
| 157 |
-
"
|
| 158 |
-
"
|
| 159 |
-
"
|
| 160 |
})
|
| 161 |
st.dataframe(df_params)
|
| 162 |
|
| 163 |
with col2:
|
| 164 |
-
if conversion_mode == "
|
| 165 |
-
st.subheader("
|
| 166 |
df_mole = pd.DataFrame({
|
| 167 |
-
"
|
| 168 |
-
"
|
| 169 |
})
|
| 170 |
st.dataframe(df_mole)
|
| 171 |
else:
|
| 172 |
-
st.subheader("
|
| 173 |
df_vol = pd.DataFrame({
|
| 174 |
-
"
|
| 175 |
-
"
|
| 176 |
})
|
| 177 |
st.dataframe(df_vol)
|
| 178 |
|
| 179 |
with col3:
|
| 180 |
-
if conversion_mode == "
|
| 181 |
-
st.subheader("
|
| 182 |
df_vol_result = pd.DataFrame({
|
| 183 |
-
"
|
| 184 |
-
"
|
| 185 |
})
|
| 186 |
st.dataframe(df_vol_result)
|
| 187 |
else:
|
| 188 |
-
st.subheader("
|
| 189 |
df_mole_result = pd.DataFrame({
|
| 190 |
-
"
|
| 191 |
-
"
|
| 192 |
})
|
| 193 |
st.dataframe(df_mole_result)
|
| 194 |
|
| 195 |
# 公式说明
|
| 196 |
st.markdown("---")
|
| 197 |
-
st.header("
|
| 198 |
-
|
| 199 |
-
if conversion_mode == "
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
| 212 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 213 |
else:
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 227 |
|
| 228 |
# 使用说明
|
| 229 |
st.markdown("---")
|
| 230 |
-
st.header("
|
| 231 |
-
st.markdown("""
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
""")
|
|
|
|
| 2 |
import pandas as pd
|
| 3 |
import math
|
| 4 |
|
| 5 |
+
# 语言配置
|
| 6 |
+
LANGUAGES = {
|
| 7 |
+
"中文": {
|
| 8 |
+
"page_title": "溶剂分数转换器",
|
| 9 |
+
"main_title": "🧪 溶剂摩尔分数与体积分数转换器",
|
| 10 |
+
"conversion_mode": "转换模式",
|
| 11 |
+
"mode_mole_to_vol": "摩尔分数 → 体积分数",
|
| 12 |
+
"mode_vol_to_mole": "体积分数 → 摩尔分数",
|
| 13 |
+
"select_conversion": "选择转换方向:",
|
| 14 |
+
"solvent_selection": "溶剂选择",
|
| 15 |
+
"select_solvents": "选择两种溶剂或自定义参数:",
|
| 16 |
+
"solvent_a": "溶剂A:",
|
| 17 |
+
"solvent_b": "溶剂B:",
|
| 18 |
+
"custom": "自定义",
|
| 19 |
+
"molar_mass": "摩尔质量",
|
| 20 |
+
"density": "密度",
|
| 21 |
+
"input_mole_fraction": "输入摩尔分数",
|
| 22 |
+
"input_volume_fraction": "输入体积分数",
|
| 23 |
+
"mole_fraction_of": "的摩尔分数",
|
| 24 |
+
"volume_fraction_of": "的体积分数",
|
| 25 |
+
"result_volume_fraction": "计算结果 - 体积分数",
|
| 26 |
+
"result_mole_fraction": "计算结果 - 摩尔分数",
|
| 27 |
+
"verification": "验证",
|
| 28 |
+
"detailed_info": "详细信息",
|
| 29 |
+
"solvent_params": "溶剂参数",
|
| 30 |
+
"solvent": "溶剂",
|
| 31 |
+
"mole_fraction": "摩尔分数",
|
| 32 |
+
"volume_fraction": "体积分数",
|
| 33 |
+
"calculation_formula": "计算公式",
|
| 34 |
+
"formula_mole_to_vol_title": "**摩尔分数转换为体积分数:**",
|
| 35 |
+
"formula_vol_to_mole_title": "**体积分数转换为摩尔分数:**",
|
| 36 |
+
"formula_where": "其中:",
|
| 37 |
+
"usage_instructions": "使用说明",
|
| 38 |
+
"instruction_1": "1. **选择转换模式**: 在侧边栏选择转换方向",
|
| 39 |
+
"instruction_2": "2. **选择溶剂**: 从预设的常见溶剂中选择,或选择\"自定义\"输入参数",
|
| 40 |
+
"instruction_3": "3. **输入数值**: 使用滑块调整摩尔分数或体积分数",
|
| 41 |
+
"instruction_4": "4. **查看结果**: 右侧显示转换结果和详细信息",
|
| 42 |
+
"note": "**注意**: 本计算假设理想混合,实际情况可能存在偏差。",
|
| 43 |
+
"language": "语言"
|
| 44 |
+
},
|
| 45 |
+
"English": {
|
| 46 |
+
"page_title": "Solvent Fraction Converter",
|
| 47 |
+
"main_title": "🧪 Solvent Mole Fraction & Volume Fraction Converter",
|
| 48 |
+
"conversion_mode": "Conversion Mode",
|
| 49 |
+
"mode_mole_to_vol": "Mole Fraction → Volume Fraction",
|
| 50 |
+
"mode_vol_to_mole": "Volume Fraction → Mole Fraction",
|
| 51 |
+
"select_conversion": "Select conversion direction:",
|
| 52 |
+
"solvent_selection": "Solvent Selection",
|
| 53 |
+
"select_solvents": "Select two solvents or customize parameters:",
|
| 54 |
+
"solvent_a": "Solvent A:",
|
| 55 |
+
"solvent_b": "Solvent B:",
|
| 56 |
+
"custom": "Custom",
|
| 57 |
+
"molar_mass": "Molar Mass",
|
| 58 |
+
"density": "Density",
|
| 59 |
+
"input_mole_fraction": "Input Mole Fraction",
|
| 60 |
+
"input_volume_fraction": "Input Volume Fraction",
|
| 61 |
+
"mole_fraction_of": "Mole fraction of",
|
| 62 |
+
"volume_fraction_of": "Volume fraction of",
|
| 63 |
+
"result_volume_fraction": "Results - Volume Fraction",
|
| 64 |
+
"result_mole_fraction": "Results - Mole Fraction",
|
| 65 |
+
"verification": "Verification",
|
| 66 |
+
"detailed_info": "Detailed Information",
|
| 67 |
+
"solvent_params": "Solvent Parameters",
|
| 68 |
+
"solvent": "Solvent",
|
| 69 |
+
"mole_fraction": "Mole Fraction",
|
| 70 |
+
"volume_fraction": "Volume Fraction",
|
| 71 |
+
"calculation_formula": "Calculation Formula",
|
| 72 |
+
"formula_mole_to_vol_title": "**Mole Fraction to Volume Fraction:**",
|
| 73 |
+
"formula_vol_to_mole_title": "**Volume Fraction to Mole Fraction:**",
|
| 74 |
+
"formula_where": "Where:",
|
| 75 |
+
"usage_instructions": "Usage Instructions",
|
| 76 |
+
"instruction_1": "1. **Select Conversion Mode**: Choose conversion direction in sidebar",
|
| 77 |
+
"instruction_2": "2. **Select Solvents**: Choose from preset common solvents or select 'Custom' to input parameters",
|
| 78 |
+
"instruction_3": "3. **Input Values**: Use sliders to adjust mole fraction or volume fraction",
|
| 79 |
+
"instruction_4": "4. **View Results**: Results and detailed information are displayed on the right",
|
| 80 |
+
"note": "**Note**: This calculation assumes ideal mixing; actual situations may deviate.",
|
| 81 |
+
"language": "Language"
|
| 82 |
+
}
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
# 常见溶剂的摩尔质量和密度数据库(中英文对照)
|
| 86 |
+
SOLVENTS_DB = {
|
| 87 |
+
"中文": {
|
| 88 |
+
"水": {"M": 18.02, "density": 1.000, "en": "Water"},
|
| 89 |
+
"乙醇": {"M": 46.07, "density": 0.789, "en": "Ethanol"},
|
| 90 |
+
"甲醇": {"M": 32.04, "density": 0.792, "en": "Methanol"},
|
| 91 |
+
"异丙醇": {"M": 60.10, "density": 0.786, "en": "Isopropanol"},
|
| 92 |
+
"丙酮": {"M": 58.08, "density": 0.784, "en": "Acetone"},
|
| 93 |
+
"乙酸乙酯": {"M": 88.11, "density": 0.902, "en": "Ethyl Acetate"},
|
| 94 |
+
"甲苯": {"M": 92.14, "density": 0.867, "en": "Toluene"},
|
| 95 |
+
"二氯甲烷": {"M": 84.93, "density": 1.326, "en": "Dichloromethane"},
|
| 96 |
+
"氯仿": {"M": 119.38, "density": 1.489, "en": "Chloroform"},
|
| 97 |
+
"四氢呋喃": {"M": 72.11, "density": 0.889, "en": "Tetrahydrofuran"},
|
| 98 |
+
"二甲基亚砜": {"M": 78.13, "density": 1.100, "en": "Dimethyl Sulfoxide"},
|
| 99 |
+
"N,N-二甲基甲酰胺": {"M": 73.09, "density": 0.944, "en": "N,N-Dimethylformamide"},
|
| 100 |
+
"乙腈": {"M": 41.05, "density": 0.786, "en": "Acetonitrile"},
|
| 101 |
+
"正己烷": {"M": 86.18, "density": 0.659, "en": "n-Hexane"},
|
| 102 |
+
"环己烷": {"M": 84.16, "density": 0.779, "en": "Cyclohexane"},
|
| 103 |
+
"苯": {"M": 78.11, "density": 0.876, "en": "Benzene"},
|
| 104 |
+
"乙二醇": {"M": 62.07, "density": 1.113, "en": "Ethylene Glycol"},
|
| 105 |
+
"甘油": {"M": 92.09, "density": 1.261, "en": "Glycerol"}
|
| 106 |
+
},
|
| 107 |
+
"English": {
|
| 108 |
+
"Water": {"M": 18.02, "density": 1.000, "cn": "水"},
|
| 109 |
+
"Ethanol": {"M": 46.07, "density": 0.789, "cn": "乙醇"},
|
| 110 |
+
"Methanol": {"M": 32.04, "density": 0.792, "cn": "甲醇"},
|
| 111 |
+
"Isopropanol": {"M": 60.10, "density": 0.786, "cn": "异丙醇"},
|
| 112 |
+
"Acetone": {"M": 58.08, "density": 0.784, "cn": "丙酮"},
|
| 113 |
+
"Ethyl Acetate": {"M": 88.11, "density": 0.902, "cn": "乙酸乙酯"},
|
| 114 |
+
"Toluene": {"M": 92.14, "density": 0.867, "cn": "甲苯"},
|
| 115 |
+
"Dichloromethane": {"M": 84.93, "density": 1.326, "cn": "二氯甲烷"},
|
| 116 |
+
"Chloroform": {"M": 119.38, "density": 1.489, "cn": "氯仿"},
|
| 117 |
+
"Tetrahydrofuran": {"M": 72.11, "density": 0.889, "cn": "四氢呋喃"},
|
| 118 |
+
"Dimethyl Sulfoxide": {"M": 78.13, "density": 1.100, "cn": "二甲基亚砜"},
|
| 119 |
+
"N,N-Dimethylformamide": {"M": 73.09, "density": 0.944, "cn": "N,N-二甲基甲酰胺"},
|
| 120 |
+
"Acetonitrile": {"M": 41.05, "density": 0.786, "cn": "乙腈"},
|
| 121 |
+
"n-Hexane": {"M": 86.18, "density": 0.659, "cn": "正己烷"},
|
| 122 |
+
"Cyclohexane": {"M": 84.16, "density": 0.779, "cn": "环己烷"},
|
| 123 |
+
"Benzene": {"M": 78.11, "density": 0.876, "cn": "苯"},
|
| 124 |
+
"Ethylene Glycol": {"M": 62.07, "density": 1.113, "cn": "乙二醇"},
|
| 125 |
+
"Glycerol": {"M": 92.09, "density": 1.261, "cn": "甘油"}
|
| 126 |
+
}
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
# 语言选择
|
| 130 |
+
language = st.sidebar.selectbox("Language/语言:", ["中文", "English"])
|
| 131 |
+
lang = LANGUAGES[language]
|
| 132 |
+
|
| 133 |
# 配置页面
|
| 134 |
st.set_page_config(
|
| 135 |
+
page_title=lang["page_title"],
|
| 136 |
page_icon="🧪",
|
| 137 |
layout="wide"
|
| 138 |
)
|
| 139 |
|
| 140 |
# 页面标题
|
| 141 |
+
st.title(lang["main_title"])
|
| 142 |
st.markdown("---")
|
| 143 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
# 侧边栏 - 转换模式选择
|
| 145 |
+
st.sidebar.header(lang["conversion_mode"])
|
| 146 |
conversion_mode = st.sidebar.radio(
|
| 147 |
+
lang["select_conversion"],
|
| 148 |
+
[lang["mode_mole_to_vol"], lang["mode_vol_to_mole"]]
|
| 149 |
)
|
| 150 |
|
| 151 |
# 溶剂选择
|
| 152 |
+
st.sidebar.header(lang["solvent_selection"])
|
| 153 |
+
st.sidebar.write(lang["select_solvents"])
|
| 154 |
+
|
| 155 |
+
# 获取当前语言的溶剂列表
|
| 156 |
+
current_solvents = SOLVENTS_DB[language]
|
| 157 |
+
solvent_names = list(current_solvents.keys()) + [lang["custom"]]
|
| 158 |
|
| 159 |
# 溶剂A选择
|
| 160 |
+
solvent_a_name = st.sidebar.selectbox(lang["solvent_a"], solvent_names)
|
| 161 |
|
| 162 |
+
if solvent_a_name == lang["custom"]:
|
| 163 |
col1, col2 = st.sidebar.columns(2)
|
| 164 |
with col1:
|
| 165 |
+
M_a = st.number_input(f"{lang['molar_mass']} A (g/mol):", value=18.02, min_value=0.1, step=0.01)
|
| 166 |
with col2:
|
| 167 |
+
rho_a = st.number_input(f"{lang['density']} A (g/cm³):", value=1.000, min_value=0.1, step=0.001)
|
| 168 |
else:
|
| 169 |
+
M_a = current_solvents[solvent_a_name]["M"]
|
| 170 |
+
rho_a = current_solvents[solvent_a_name]["density"]
|
| 171 |
+
st.sidebar.write(f"{lang['molar_mass']}: {M_a} g/mol")
|
| 172 |
+
st.sidebar.write(f"{lang['density']}: {rho_a} g/cm³")
|
| 173 |
|
| 174 |
# 溶剂B选择
|
| 175 |
+
solvent_b_name = st.sidebar.selectbox(lang["solvent_b"], solvent_names)
|
| 176 |
|
| 177 |
+
if solvent_b_name == lang["custom"]:
|
| 178 |
col1, col2 = st.sidebar.columns(2)
|
| 179 |
with col1:
|
| 180 |
+
M_b = st.number_input(f"{lang['molar_mass']} B (g/mol):", value=46.07, min_value=0.1, step=0.01)
|
| 181 |
with col2:
|
| 182 |
+
rho_b = st.number_input(f"{lang['density']} B (g/cm³):", value=0.789, min_value=0.1, step=0.001)
|
| 183 |
else:
|
| 184 |
+
M_b = current_solvents[solvent_b_name]["M"]
|
| 185 |
+
rho_b = current_solvents[solvent_b_name]["density"]
|
| 186 |
+
st.sidebar.write(f"{lang['molar_mass']}: {M_b} g/mol")
|
| 187 |
+
st.sidebar.write(f"{lang['density']}: {rho_b} g/cm³")
|
| 188 |
|
| 189 |
# 主界面内容
|
| 190 |
col1, col2 = st.columns(2)
|
| 191 |
|
| 192 |
+
if conversion_mode == lang["mode_mole_to_vol"]:
|
| 193 |
with col1:
|
| 194 |
+
st.header(lang["input_mole_fraction"])
|
| 195 |
+
x_a = st.number_input(
|
| 196 |
+
f"{lang['mole_fraction_of']} {solvent_a_name} (x_A):",
|
| 197 |
min_value=0.0,
|
| 198 |
max_value=1.0,
|
| 199 |
value=0.5,
|
| 200 |
+
step=0.001,
|
| 201 |
+
format="%.4f"
|
| 202 |
)
|
| 203 |
x_b = 1.0 - x_a
|
| 204 |
+
st.write(f"{lang['mole_fraction_of']} {solvent_b_name} (x_B): {x_b:.4f}")
|
| 205 |
|
| 206 |
# 计算体积分数
|
|
|
|
| 207 |
V_ratio_a = x_a * M_a / rho_a
|
| 208 |
V_ratio_b = x_b * M_b / rho_b
|
| 209 |
V_total = V_ratio_a + V_ratio_b
|
|
|
|
| 215 |
phi_a = phi_b = 0
|
| 216 |
|
| 217 |
with col2:
|
| 218 |
+
st.header(lang["result_volume_fraction"])
|
| 219 |
+
st.metric(f"{lang['volume_fraction_of']} {solvent_a_name} (φ_A)", f"{phi_a:.4f}")
|
| 220 |
+
st.metric(f"{lang['volume_fraction_of']} {solvent_b_name} (φ_B)", f"{phi_b:.4f}")
|
| 221 |
|
| 222 |
# 验证
|
| 223 |
+
st.write(f"{lang['verification']}: φ_A + φ_B = {phi_a + phi_b:.4f}")
|
| 224 |
|
| 225 |
else: # 体积分数 → 摩尔分数
|
| 226 |
with col1:
|
| 227 |
+
st.header(lang["input_volume_fraction"])
|
| 228 |
+
phi_a = st.number_input(
|
| 229 |
+
f"{lang['volume_fraction_of']} {solvent_a_name} (φ_A):",
|
| 230 |
min_value=0.0,
|
| 231 |
max_value=1.0,
|
| 232 |
value=0.5,
|
| 233 |
+
step=0.001,
|
| 234 |
+
format="%.4f"
|
| 235 |
)
|
| 236 |
phi_b = 1.0 - phi_a
|
| 237 |
+
st.write(f"{lang['volume_fraction_of']} {solvent_b_name} (φ_B): {phi_b:.4f}")
|
| 238 |
|
| 239 |
# 计算摩尔分数
|
|
|
|
| 240 |
n_ratio_a = phi_a * rho_a / M_a
|
| 241 |
n_ratio_b = phi_b * rho_b / M_b
|
| 242 |
n_total = n_ratio_a + n_ratio_b
|
|
|
|
| 248 |
x_a = x_b = 0
|
| 249 |
|
| 250 |
with col2:
|
| 251 |
+
st.header(lang["result_mole_fraction"])
|
| 252 |
+
st.metric(f"{lang['mole_fraction_of']} {solvent_a_name} (x_A)", f"{x_a:.4f}")
|
| 253 |
+
st.metric(f"{lang['mole_fraction_of']} {solvent_b_name} (x_B)", f"{x_b:.4f}")
|
| 254 |
|
| 255 |
# 验证
|
| 256 |
+
st.write(f"{lang['verification']}: x_A + x_B = {x_a + x_b:.4f}")
|
| 257 |
+
|
| 258 |
# 详细信息展示
|
| 259 |
st.markdown("---")
|
| 260 |
+
st.header(lang["detailed_info"])
|
| 261 |
|
| 262 |
col1, col2, col3 = st.columns(3)
|
| 263 |
|
| 264 |
with col1:
|
| 265 |
+
st.subheader(lang["solvent_params"])
|
| 266 |
df_params = pd.DataFrame({
|
| 267 |
+
lang["solvent"]: [solvent_a_name, solvent_b_name],
|
| 268 |
+
f"{lang['molar_mass']} (g/mol)": [M_a, M_b],
|
| 269 |
+
f"{lang['density']} (g/cm³)": [rho_a, rho_b]
|
| 270 |
})
|
| 271 |
st.dataframe(df_params)
|
| 272 |
|
| 273 |
with col2:
|
| 274 |
+
if conversion_mode == lang["mode_mole_to_vol"]:
|
| 275 |
+
st.subheader(lang["mole_fraction"])
|
| 276 |
df_mole = pd.DataFrame({
|
| 277 |
+
lang["solvent"]: [solvent_a_name, solvent_b_name],
|
| 278 |
+
lang["mole_fraction"]: [x_a, x_b]
|
| 279 |
})
|
| 280 |
st.dataframe(df_mole)
|
| 281 |
else:
|
| 282 |
+
st.subheader(lang["volume_fraction"])
|
| 283 |
df_vol = pd.DataFrame({
|
| 284 |
+
lang["solvent"]: [solvent_a_name, solvent_b_name],
|
| 285 |
+
lang["volume_fraction"]: [phi_a, phi_b]
|
| 286 |
})
|
| 287 |
st.dataframe(df_vol)
|
| 288 |
|
| 289 |
with col3:
|
| 290 |
+
if conversion_mode == lang["mode_mole_to_vol"]:
|
| 291 |
+
st.subheader(lang["volume_fraction"])
|
| 292 |
df_vol_result = pd.DataFrame({
|
| 293 |
+
lang["solvent"]: [solvent_a_name, solvent_b_name],
|
| 294 |
+
lang["volume_fraction"]: [phi_a, phi_b]
|
| 295 |
})
|
| 296 |
st.dataframe(df_vol_result)
|
| 297 |
else:
|
| 298 |
+
st.subheader(lang["mole_fraction"])
|
| 299 |
df_mole_result = pd.DataFrame({
|
| 300 |
+
lang["solvent"]: [solvent_a_name, solvent_b_name],
|
| 301 |
+
lang["mole_fraction"]: [x_a, x_b]
|
| 302 |
})
|
| 303 |
st.dataframe(df_mole_result)
|
| 304 |
|
| 305 |
# 公式说明
|
| 306 |
st.markdown("---")
|
| 307 |
+
st.header(lang["calculation_formula"])
|
| 308 |
+
|
| 309 |
+
if conversion_mode == lang["mode_mole_to_vol"]:
|
| 310 |
+
if language == "中文":
|
| 311 |
+
st.markdown(f"""
|
| 312 |
+
{lang["formula_mole_to_vol_title"]}
|
| 313 |
+
|
| 314 |
+
$$\\phi_A = \\frac{{x_A \\cdot M_A / \\rho_A}}{{x_A \\cdot M_A / \\rho_A + x_B \\cdot M_B / \\rho_B}}$$
|
| 315 |
+
|
| 316 |
+
$$\\phi_B = \\frac{{x_B \\cdot M_B / \\rho_B}}{{x_A \\cdot M_A / \\rho_A + x_B \\cdot M_B / \\rho_B}}$$
|
| 317 |
+
|
| 318 |
+
{lang["formula_where"]}
|
| 319 |
+
- $x_A, x_B$: 摩尔分数
|
| 320 |
+
- $\\phi_A, \\phi_B$: 体积分数
|
| 321 |
+
- $M_A, M_B$: 摩尔质量 (g/mol)
|
| 322 |
+
- $\\rho_A, \\rho_B$: 密度 (g/cm³)
|
| 323 |
+
""")
|
| 324 |
+
else:
|
| 325 |
+
st.markdown(f"""
|
| 326 |
+
{lang["formula_mole_to_vol_title"]}
|
| 327 |
+
|
| 328 |
+
$$\\phi_A = \\frac{{x_A \\cdot M_A / \\rho_A}}{{x_A \\cdot M_A / \\rho_A + x_B \\cdot M_B / \\rho_B}}$$
|
| 329 |
+
|
| 330 |
+
$$\\phi_B = \\frac{{x_B \\cdot M_B / \\rho_B}}{{x_A \\cdot M_A / \\rho_A + x_B \\cdot M_B / \\rho_B}}$$
|
| 331 |
+
|
| 332 |
+
{lang["formula_where"]}
|
| 333 |
+
- $x_A, x_B$: Mole fractions
|
| 334 |
+
- $\\phi_A, \\phi_B$: Volume fractions
|
| 335 |
+
- $M_A, M_B$: Molar mass (g/mol)
|
| 336 |
+
- $\\rho_A, \\rho_B$: Density (g/cm³)
|
| 337 |
+
""")
|
| 338 |
else:
|
| 339 |
+
if language == "中文":
|
| 340 |
+
st.markdown(f"""
|
| 341 |
+
{lang["formula_vol_to_mole_title"]}
|
| 342 |
+
|
| 343 |
+
$$x_A = \\frac{{\\phi_A \\cdot \\rho_A / M_A}}{{\\phi_A \\cdot \\rho_A / M_A + \\phi_B \\cdot \\rho_B / M_B}}$$
|
| 344 |
+
|
| 345 |
+
$$x_B = \\frac{{\\phi_B \\cdot \\rho_B / M_B}}{{\\phi_A \\cdot \\rho_A / M_A + \\phi_B \\cdot \\rho_B / M_B}}$$
|
| 346 |
+
|
| 347 |
+
{lang["formula_where"]}
|
| 348 |
+
- $\\phi_A, \\phi_B$: 体积分数
|
| 349 |
+
- $x_A, x_B$: 摩尔分数
|
| 350 |
+
- $M_A, M_B$: 摩尔质量 (g/mol)
|
| 351 |
+
- $\\rho_A, \\rho_B$: 密度 (g/cm³)
|
| 352 |
+
""")
|
| 353 |
+
else:
|
| 354 |
+
st.markdown(f"""
|
| 355 |
+
{lang["formula_vol_to_mole_title"]}
|
| 356 |
+
|
| 357 |
+
$$x_A = \\frac{{\\phi_A \\cdot \\rho_A / M_A}}{{\\phi_A \\cdot \\rho_A / M_A + \\phi_B \\cdot \\rho_B / M_B}}$$
|
| 358 |
+
|
| 359 |
+
$$x_B = \\frac{{\\phi_B \\cdot \\rho_B / M_B}}{{\\phi_A \\cdot \\rho_A / M_A + \\phi_B \\cdot \\rho_B / M_B}}$$
|
| 360 |
+
|
| 361 |
+
{lang["formula_where"]}
|
| 362 |
+
- $\\phi_A, \\phi_B$: Volume fractions
|
| 363 |
+
- $x_A, x_B$: Mole fractions
|
| 364 |
+
- $M_A, M_B$: Molar mass (g/mol)
|
| 365 |
+
- $\\rho_A, \\rho_B$: Density (g/cm³)
|
| 366 |
+
""")
|
| 367 |
|
| 368 |
# 使用说明
|
| 369 |
st.markdown("---")
|
| 370 |
+
st.header(lang["usage_instructions"])
|
| 371 |
+
st.markdown(f"""
|
| 372 |
+
{lang["instruction_1"]}
|
| 373 |
+
{lang["instruction_2"]}
|
| 374 |
+
{lang["instruction_3"]}
|
| 375 |
+
{lang["instruction_4"]}
|
| 376 |
+
|
| 377 |
+
{lang["note"]}
|
| 378 |
""")
|