use std::path::Path; use std::process::Command; fn main() { // Re-run build script if dashboard files change println!("cargo:rerun-if-changed=../../dashboard/src"); println!("cargo:rerun-if-changed=../../dashboard/package.json"); println!("cargo:rerun-if-changed=../../dashboard/index.html"); // Skip building dashboard in Docker / CI environments if requested let skip_build = std::env::var("SKIP_DASHBOARD_BUILD") .map(|v| v == "1" || v == "true") .unwrap_or(false); if skip_build { println!("cargo:warning=SKIP_DASHBOARD_BUILD 已启用,跳过前端 Dashboard 编译。"); return; } let dashboard_dir = Path::new("../../dashboard"); if !dashboard_dir.exists() { println!("cargo:warning=未检测到 dashboard 目录,跳过前端构建。"); return; } let node_modules_exist = dashboard_dir.join("node_modules").exists(); if !node_modules_exist { println!("cargo:warning=未检测到 dashboard/node_modules,正在执行 npm install..."); let status = Command::new("npm") .arg("install") .current_dir(dashboard_dir) .status(); match status { Ok(s) if s.success() => { println!("cargo:warning=前端依赖 (npm install) 执行成功。"); } _ => { panic!("前端部署阶段:执行 'npm install' 失败!请确认环境中已安装且具备可用的 Node/NPM 工具。若意在进行服务端原生单独打包装订而完全不需要绑定前端静态页面资源,可以设置环境变量 SKIP_DASHBOARD_BUILD=1"); } } } let dist_index = dashboard_dir.join("dist/index.html"); let needs_build = if !dist_index.exists() { true } else { fn latest_mtime(dir: &Path) -> std::time::SystemTime { let mut max = std::fs::metadata(dir) .and_then(|m| m.modified()) .unwrap_or(std::time::SystemTime::UNIX_EPOCH); if dir.is_dir() { if let Ok(entries) = std::fs::read_dir(dir) { for entry in entries.flatten() { let t = latest_mtime(&entry.path()); if t > max { max = t; } } } } max } let dist_time = std::fs::metadata(&dist_index) .and_then(|m| m.modified()) .unwrap_or(std::time::SystemTime::UNIX_EPOCH); latest_mtime(&dashboard_dir.join("src")) > dist_time || latest_mtime(&dashboard_dir.join("package.json")) > dist_time || latest_mtime(&dashboard_dir.join("index.html")) > dist_time }; if needs_build { println!("cargo:warning=正在打包前端 Dashboard 静态资源 (npm run build)..."); let status = Command::new("npm") .arg("run") .arg("build") .current_dir(dashboard_dir) .status(); match status { Ok(s) if s.success() => { println!("cargo:warning=前端 Dashboard 静态资源打包成功。"); } _ => { panic!("前端部署阶段:执行 'npm run build' 失败,无法编译生成面板资源包!未免造生功能存在组件缺憾和页面载入留白的严重程序构建散落碎片,本项预编译保护链早已锁严封口,并当即制停本次流程。"); } } } else { println!("cargo:warning=检测到前端 Dashboard 静态资源已是最新,跳过构建。"); } }