yggdrasil/pages/admin/settings/
system_section.rs1use leptos::prelude::*;
7use leptos::task::spawn_local;
8
9use super::kit::SettingsCard;
10use super::SettingsSection;
11use crate::api::settings::get_system_info;
12use crate::models::settings::SystemInfo;
13
14fn rows(i: &SystemInfo) -> Vec<(&'static str, &'static str, String, &'static str)> {
16 let on_off = |b: bool| if b { "开启" } else { "关闭" }.to_string();
17 vec![
18 (
19 "数据库连接",
20 "DATABASE_URL",
21 i.database_url_masked.clone(),
22 "启动时必需",
23 ),
24 ("日志级别", "RUST_LOG", i.rust_log.clone(), "tracing 过滤器"),
25 (
26 "连接池大小",
27 "DB_POOL_SIZE",
28 i.db_pool_size.to_string(),
29 "deadpool 连接池",
30 ),
31 (
32 "查询超时",
33 "STATEMENT_TIMEOUT_SECS",
34 format!("{} 秒", i.statement_timeout_secs),
35 "写进连接池选项",
36 ),
37 (
38 "SSR 缓存时长",
39 "SSR_CACHE_SECS",
40 format!("{} 秒", i.ssr_cache_secs),
41 "增量渲染缓存",
42 ),
43 (
44 "响应压缩",
45 "COMPRESSION_ALGORITHMS",
46 if i.compression_algorithms.is_empty() {
47 "关闭".into()
48 } else {
49 i.compression_algorithms.clone()
50 },
51 "压缩层启动时构建",
52 ),
53 (
54 "版本响应头",
55 "EXPOSE_VERSION_HEADERS",
56 on_off(i.expose_version_headers),
57 "中间件启动时挂载",
58 ),
59 (
60 "Docker Socket",
61 "DOCKER_SOCKET_PATH",
62 i.docker_socket_path.clone(),
63 "代码运行器连接 Docker",
64 ),
65 (
66 "MCP 加密主密钥",
67 "MCP_TOKEN_ENC_KEY",
68 if i.mcp_token_enc_key_set {
69 "已设置".into()
70 } else {
71 "未设置".into()
72 },
73 "轮换会使旧令牌无法解密",
74 ),
75 (
76 "启动迁移超时",
77 "MIGRATE_STARTUP_TIMEOUT_SECS",
78 format!("{} 秒", i.migrate_startup_timeout_secs),
79 "只在启动期间生效",
80 ),
81 (
82 "系统采样间隔",
83 "SYSINFO_SAMPLE_SECS",
84 format!("{} 秒", i.sysinfo_sample_secs),
85 "采样循环启动时读取",
86 ),
87 (
88 "日志查看器级别",
89 "LOG_VIEWER_LEVEL",
90 i.log_viewer_level.clone(),
91 "/admin/logs 入库级别,独立于 RUST_LOG",
92 ),
93 (
94 "备份导入上限",
95 "BACKUP_IMPORT_MAX_MB",
96 format!("{} MB", i.backup_import_max_mb),
97 "反代 body 上限需同步放大",
98 ),
99 (
100 "旧发布资源目录",
101 "YGG_PREVIOUS_PUBLIC_DIR",
102 if i.previous_public_dir.is_empty() {
103 "未设置".into()
104 } else {
105 i.previous_public_dir.clone()
106 },
107 "滚动发布时保留旧 hash 资源",
108 ),
109 ]
110}
111
112#[component]
114pub fn SystemSection() -> impl IntoView {
115 let info = RwSignal::new(None::<SystemInfo>);
116 let failed = RwSignal::new(false);
117 Effect::new(move |loaded: Option<()>| {
119 if loaded.is_some() {
120 return;
121 }
122 spawn_local(async move {
123 match get_system_info().await {
124 Ok(i) => info.set(Some(i)),
125 Err(_) => failed.set(true),
126 }
127 });
128 });
129 let ready = Signal::derive(move || info.with(|i| i.is_some()));
130 view! {
131 <SettingsCard
132 section=SettingsSection::System
133 description="进程启动时读取的环境变量,这里只展示;修改后需重启服务。"
134 ready=ready
135 load_failed=failed
136 >
137 {move || {
138 info.get()
139 .map(|i| {
140 view! {
141 <dl class="settings-readonly">
142 {rows(&i)
143 .into_iter()
144 .map(|(label, env, value, hint)| {
145 view! {
146 <div class="settings-readonly-row">
147 <dt>
148 <span>{label}</span>
149 <code>{env}</code>
150 </dt>
151 <dd>
152 <span class="settings-mono">{value}</span>
153 <small>{hint}</small>
154 </dd>
155 </div>
156 }
157 })
158 .collect_view()}
159 </dl>
160 }
161 })
162 }}
163 </SettingsCard>
164 }
165}