@@ -10,6 +10,7 @@ use tauri::{AppHandle, Emitter};
1010pub struct EnvironmentVersion {
1111 pub version : String ,
1212 pub download_url : String ,
13+ pub fallback_url : Option < String > , // 备用下载地址(如 GitHub URL)
1314 pub install_path : Option < String > ,
1415 pub is_installed : bool ,
1516 pub size : Option < u64 > ,
@@ -98,7 +99,7 @@ impl EnvironmentManager {
9899 let provider = self
99100 . providers
100101 . get ( language)
101- . ok_or_else ( || format ! ( "暂未支持 {} 语言,请前往 github 提供 issus " , language) ) ?;
102+ . ok_or_else ( || format ! ( "暂未支持 {} 语言,请前往 github 提供 issues " , language) ) ?;
102103
103104 info ! ( "获取 {} 环境信息" , language) ;
104105
@@ -126,7 +127,7 @@ impl EnvironmentManager {
126127 let provider = self
127128 . providers
128129 . get ( language)
129- . ok_or_else ( || format ! ( "暂未支持 {} 语言,请前往 github 提供 issus " , language) ) ?;
130+ . ok_or_else ( || format ! ( "暂未支持 {} 语言,请前往 github 提供 issues " , language) ) ?;
130131
131132 info ! ( "开始下载并安装 {} 版本 {}" , language, version) ;
132133 provider. download_and_install ( version, app_handle) . await
@@ -136,7 +137,7 @@ impl EnvironmentManager {
136137 let provider = self
137138 . providers
138139 . get ( language)
139- . ok_or_else ( || format ! ( "暂未支持 {} 语言,请前往 github 提供 issus " , language) ) ?;
140+ . ok_or_else ( || format ! ( "暂未支持 {} 语言,请前往 github 提供 issues " , language) ) ?;
140141
141142 info ! ( "切换 {} 到版本 {}" , language, version) ;
142143 provider. switch_version ( version) . await
@@ -175,3 +176,102 @@ pub fn emit_download_progress(
175176 error ! ( "发送下载进度事件失败: {}" , e) ;
176177 }
177178}
179+
180+ // 将 GitHub 下载 URL 转换为 CDN 镜像 URL
181+ pub fn convert_to_cdn_url (
182+ original_url : & str ,
183+ language : & str ,
184+ version : & str ,
185+ ) -> Result < String , String > {
186+ use crate :: config:: get_app_config_internal;
187+
188+ let config = get_app_config_internal ( ) . map_err ( |e| format ! ( "获取配置失败: {}" , e) ) ?;
189+
190+ let mirror_config = config. environment_mirror . as_ref ( ) ;
191+ let enabled = mirror_config. and_then ( |m| m. enabled ) . unwrap_or ( false ) ;
192+
193+ if !enabled {
194+ return Ok ( original_url. to_string ( ) ) ;
195+ }
196+
197+ let base_url = mirror_config
198+ . and_then ( |m| m. base_url . as_ref ( ) )
199+ . ok_or_else ( || "CDN 基础 URL 未配置" . to_string ( ) ) ?;
200+
201+ // 从原始 URL 中提取文件名
202+ let file_name = original_url
203+ . split ( '/' )
204+ . last ( )
205+ . ok_or_else ( || "无效的下载 URL" . to_string ( ) ) ?;
206+
207+ // 构建 CDN URL: {base_url}/{language}/{version}/{filename}
208+ let cdn_url = format ! (
209+ "{}/{}/{}/{}" ,
210+ base_url. trim_end_matches( '/' ) ,
211+ language,
212+ version,
213+ file_name
214+ ) ;
215+
216+ info ! ( "转换下载 URL: {} -> {}" , original_url, cdn_url) ;
217+ Ok ( cdn_url)
218+ }
219+
220+ // 尝试从 CDN 下载,失败则回退到原始 URL
221+ pub async fn download_with_fallback (
222+ client : & reqwest:: Client ,
223+ original_url : & str ,
224+ language : & str ,
225+ version : & str ,
226+ ) -> Result < reqwest:: Response , String > {
227+ use crate :: config:: get_app_config_internal;
228+
229+ // 检查是否启用自动回退
230+ let fallback_enabled = get_app_config_internal ( )
231+ . ok ( )
232+ . and_then ( |config| config. environment_mirror )
233+ . and_then ( |mirror| mirror. fallback_enabled )
234+ . unwrap_or ( false ) ;
235+
236+ // 首先尝试从 CDN 下载
237+ match convert_to_cdn_url ( original_url, language, version) {
238+ Ok ( cdn_url) if cdn_url != original_url => {
239+ info ! ( "尝试从 CDN 下载: {}" , cdn_url) ;
240+ match client. get ( & cdn_url) . send ( ) . await {
241+ Ok ( response) if response. status ( ) . is_success ( ) => {
242+ info ! ( "CDN 下载成功" ) ;
243+ return Ok ( response) ;
244+ }
245+ Ok ( response) => {
246+ let status = response. status ( ) ;
247+ if fallback_enabled {
248+ info ! ( "CDN 下载失败 (HTTP {}), 回退到原始 URL" , status) ;
249+ } else {
250+ return Err ( format ! ( "CDN 下载失败 (HTTP {}), 未启用自动回退" , status) ) ;
251+ }
252+ }
253+ Err ( e) => {
254+ if fallback_enabled {
255+ info ! ( "CDN 下载失败 ({}), 回退到原始 URL" , e) ;
256+ } else {
257+ return Err ( format ! ( "CDN 下载失败 ({}), 未启用自动回退" , e) ) ;
258+ }
259+ }
260+ }
261+ }
262+ Ok ( _) => {
263+ info ! ( "CDN 镜像未启用,使用原始 URL" ) ;
264+ }
265+ Err ( e) => {
266+ info ! ( "CDN URL 转换失败 ({}), 使用原始 URL" , e) ;
267+ }
268+ }
269+
270+ // 回退到原始 URL
271+ info ! ( "从原始 URL 下载: {}" , original_url) ;
272+ client
273+ . get ( original_url)
274+ . send ( )
275+ . await
276+ . map_err ( |e| format ! ( "下载失败: {}" , e) )
277+ }
0 commit comments