import { readFileSync, writeFileSync, cpSync, mkdirSync, rmSync, statSync } from 'node:fs' import { resolve, basename } from 'node:path' import type { Plugin } from 'vite' import AdmZip from 'adm-zip' /** * 打包时自增版本号、写入构建时间、复制配置文件、压缩 dist 为 zip */ export function bumpVersion(mode: string, buildTime: string): Plugin { return { name: 'bump-version-and-copy', writeBundle(options) { const outDir = options.dir if (!outDir) return const src = `src/config/plugin.properties.${mode}` let content = readFileSync(src, 'utf-8') const match = content.match(/version_code=(\d+)/) if (!match) return const oldCode = Number(match[1]) const newCode = oldCode + 1 // 版本号规则:version_code 按 A BB CC 映射为三段版本号 A.B.C // 示例:10000 → 1.0.0,10102 → 1.1.2 const major = Math.floor(newCode / 10000) const minor = Math.floor((newCode % 10000) / 100) const patch = newCode % 100 const versionName = `${major}.${minor}.${patch}` content = content .replace(/version_code=\d+/, `version_code=${newCode}`) .replace(/version_name=[^;\n]+/, `version_name=${versionName}`) const buildTimeLine = `build_time=${buildTime};` content = /build_time=[^;\n]*;?/.test(content) ? content.replace(/build_time=[^;\n]*;?/, buildTimeLine) : `${content}${content.endsWith('\n') ? '' : '\n'}${buildTimeLine}\n` writeFileSync(src, content) writeFileSync(resolve(outDir, '..', 'plugin.properties'), content) // 复制 config.properties 到 dist/www/ cpSync('src/config/config.properties', resolve(outDir, 'config.properties')) console.log( `[plugin.properties] version: ${oldCode} → ${newCode} (${versionName}), build time: ${buildTime}`, ) // 压缩 dist 为 zip(使用 adm-zip,跨平台兼容) const distDir = resolve(outDir, '..') const environmentName = mode.toUpperCase() const zipDir = resolve(distDir, environmentName) const zipName = `头寸管理2.0_version_${versionName}.zip` const zipPath = resolve(zipDir, zipName) const zip = new AdmZip() const zipStartedAt = Date.now() zip.addLocalFolder(resolve(distDir, 'www'), 'www') zip.addLocalFile(resolve(distDir, 'plugin.properties')) mkdirSync(zipDir, { recursive: true }) rmSync(zipPath, { force: true }) zip.writeZip(zipPath) const zipSize = statSync(zipPath).size const zipRelativePath = `${basename(distDir)}/${environmentName}/${zipName}` const zipDuration = Date.now() - zipStartedAt console.log( [ '', '================ ZIP 压缩完成 ================', `构建环境:${environmentName}`, `版本信息:${versionName}(version_code=${newCode})`, `构建时间:${buildTime}`, `文件名称:${zipName}`, `相对路径:${zipRelativePath}`, `绝对路径:${zipPath}`, `文件大小:${formatFileSize(zipSize)}(${zipSize} bytes)`, `压缩耗时:${zipDuration} ms`, '压缩内容:www/、plugin.properties', '==============================================', ].join('\n'), ) }, } } function formatFileSize(bytes: number) { if (bytes < 1024) return `${bytes} B` const units = ['KB', 'MB', 'GB'] let size = bytes / 1024 let unitIndex = 0 while (size >= 1024 && unitIndex < units.length - 1) { size /= 1024 unitIndex += 1 } return `${size.toFixed(2)} ${units[unitIndex]}` }