From 19bc1a32ef9c678d93c22d53307b810af74d3bbd Mon Sep 17 00:00:00 2001 From: zhang1106 <849185023@qq.com> Date: Tue, 17 Mar 2026 13:22:24 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=E7=8A=B6=E6=80=81=E6=A3=80=E6=B5=8B=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在 buildFrontend 函数中添加 checkFrontendNeedsBuild 方法,用于检测前端是否需要重新构建。该方法会检查以下情况: 1. dist 目录是否存在 2. 源码或配置文件是否有 git 变更 3. 源码修改时间是否晚于构建产物 根据检测结果决定是否执行构建,避免不必要的构建操作 --- update.js | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 8 deletions(-) diff --git a/update.js b/update.js index aceb55c..62f7497 100644 --- a/update.js +++ b/update.js @@ -429,6 +429,70 @@ function runMigrations(options) { return { success: true, warning: true }; } +function checkFrontendNeedsBuild() { + const frontendPath = path.join(__dirname, 'frontend'); + const distPath = path.join(frontendPath, 'dist'); + const srcPath = path.join(frontendPath, 'src'); + + if (!fs.existsSync(distPath)) { + return { needBuild: true, reason: 'dist 目录不存在' }; + } + + try { + const gitDiff = execSync('git diff HEAD~1 --name-only -- "frontend/src" "frontend/package.json" "frontend/vite.config.*" "frontend/index.html" 2>nul', { + encoding: 'utf8', + stdio: ['pipe', 'pipe', 'pipe'], + cwd: __dirname + }).trim(); + + if (gitDiff) { + const changedFiles = gitDiff.split('\n').filter(f => f).slice(0, 3); + return { + needBuild: true, + reason: `源码或配置有更新: ${changedFiles.join(', ')}${gitDiff.split('\n').length > 3 ? '...' : ''}` + }; + } + } catch { + // Git 检查失败,继续其他检测 + } + + try { + let latestSrcTime = 0; + let latestDistTime = 0; + + const getLatestTime = (dir) => { + let latest = 0; + const files = fs.readdirSync(dir); + for (const file of files) { + const filePath = path.join(dir, file); + const stat = fs.statSync(filePath); + if (stat.isDirectory()) { + latest = Math.max(latest, getLatestTime(filePath)); + } else { + latest = Math.max(latest, stat.mtimeMs); + } + } + return latest; + }; + + if (fs.existsSync(srcPath)) { + latestSrcTime = getLatestTime(srcPath); + } + if (fs.existsSync(distPath)) { + latestDistTime = getLatestTime(distPath); + } + + if (latestSrcTime > latestDistTime) { + return { needBuild: true, reason: '源码修改时间晚于构建产物' }; + } + } catch { + // 时间检测失败,保守起见执行构建 + return { needBuild: true, reason: '构建状态检测失败' }; + } + + return { needBuild: false, reason: '构建产物已是最新' }; +} + function buildFrontend(options) { if (options.skipBuild) { log.info('已跳过前端构建'); @@ -438,20 +502,28 @@ function buildFrontend(options) { const frontendPath = path.join(__dirname, 'frontend'); if (options.dryRun) { - log.subStep('[模拟] 构建前端'); + log.subStep('[模拟] 检测前端构建状态'); return { success: true, dryRun: true }; } - log.subStep('构建前端...'); - const buildResult = runCommand('npm run build', { cwd: frontendPath }); + log.subStep('检测前端构建状态...'); + const buildCheck = checkFrontendNeedsBuild(); - if (buildResult.success) { - log.success('前端构建完成'); - return { success: true }; + if (buildCheck.needBuild) { + log.info(`前端需要构建: ${buildCheck.reason}`); + const buildResult = runCommand('npm run build', { cwd: frontendPath }); + + if (buildResult.success) { + log.success('前端构建完成'); + return { success: true }; + } + + log.error('前端构建失败'); + return { success: false }; } - log.error('前端构建失败'); - return { success: false }; + log.success(`前端构建产物已是最新 (${buildCheck.reason})`); + return { success: true, skipped: true }; } function restartServices(options) {