import * as fs from 'fs'; import { resolve } from 'path'; import { execSync } from 'child_process'; import * as path from 'path'; import consola from 'consola'; import axios from 'axios'; import { URL } from 'url'; // 错误信息常量 const ErrorMessages = { NO_SOURCE: '请提供源文件路径或URL', INVALID_FILE_TYPE: '无效的文件类型,仅支持 PNG、JPG、JPEG 和 GIF', FILE_NOT_EXIST: '源文件不存在', DOWNLOAD_FAILED: '文件下载失败:', COPY_FAILED: '文件复制失败:', UNEXPECTED_ERROR: '发生意外错误:', }; /** * 从URL下载文件到指定目录 * @param url 文件的URL地址 * @param destination 目标保存路径 */ async function downloadFile(url: string, destination: string): Promise { try { const response = await axios({ url, method: 'GET', responseType: 'stream' }); const writer = fs.createWriteStream(destination); response.data.pipe(writer); return new Promise((resolve, reject) => { writer.on('finish', resolve); writer.on('error', reject); }); } catch (error) { throw new Error(`${ErrorMessages.DOWNLOAD_FAILED} ${error.message}`); } } /** * 复制文件到指定目录 * @param source 源文件路径 * @param destination 目标路径 */ function copy(source: string, destination: string): void { try { execSync(`cp ${source} ${destination}`); } catch (error) { throw new Error(`${ErrorMessages.COPY_FAILED} ${error.message}`); } } /** * 验证字符串是否为有效URL * @param string 待验证的字符串 * @returns boolean 是否为有效URL */ function isValidUrl(string: string): boolean { try { new URL(string); return true; } catch { return false; } } /** * 验证文件是否为支持的图片类型 * @param filePath 文件路径 * @returns boolean 是否为支持的图片类型 */ function isValidImageFile(filePath: string): boolean { const validExtensions = ['.png', '.jpg', '.jpeg', '.gif']; const ext = path.extname(filePath).toLowerCase(); return validExtensions.includes(ext); } /** * 主函数 - 处理Logo替换逻辑 */ async function main(): Promise { try { // 获取命令行参数中的源文件路径 const sourcePath = process.argv[2]; if (!sourcePath) { throw new Error(ErrorMessages.NO_SOURCE); } const baseDir: string = resolve('./'); const destinationPath = './res/icon/android/logo.png'; // 打印初始信息 consola.info('开始替换Logo'); consola.info('当前目录: ' + baseDir); consola.info('源文件: ' + sourcePath); // 验证文件类型 if (!isValidImageFile(sourcePath)) { throw new Error(ErrorMessages.INVALID_FILE_TYPE); } // 根据源文件类型处理(URL或本地文件) if (isValidUrl(sourcePath)) { consola.info('正在从URL下载文件...'); const tempFile = path.join(baseDir, 'temp-logo' + path.extname(sourcePath)); try { // 下载并替换文件 await downloadFile(sourcePath, tempFile); copy(tempFile, destinationPath); consola.success('Logo替换成功'); } finally { // 清理临时文件 if (fs.existsSync(tempFile)) { fs.unlinkSync(tempFile); } } } else { // 处理本地文件 const localPath = path.resolve(sourcePath); if (!fs.existsSync(localPath)) { throw new Error(ErrorMessages.FILE_NOT_EXIST); } // 复制文件 copy(localPath, destinationPath); consola.success('Logo替换成功'); } } catch (error) { consola.error('Logo替换失败:', error.message); process.exit(1); } } // 执行主函数 main().catch(error => { consola.error(ErrorMessages.UNEXPECTED_ERROR, error); process.exit(1); });