diff --git a/package.json b/package.json index c1f40a9..0b5f6a1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "scripts": { - "release-mp-weixin": "node scripts/mp-weixin.patch.js" + "mp-weixin": "node scripts/mp-weixin.patch.js" }, "devDependencies": { "terser-webpack-plugin": "^5.3.10" diff --git a/scripts/create-zip.js b/scripts/create-zip.js new file mode 100644 index 0000000..74a5dfa --- /dev/null +++ b/scripts/create-zip.js @@ -0,0 +1,58 @@ +const fs = require('fs'); +const fsp = fs.promises; +const path = require('path'); + +const { exec } = require('child_process'); +const { promisify } = require('util'); +const execAsync = promisify(exec); + +/** + * 使用系统命令创建ZIP(跨平台) + * @param {string} sourceDir - 要压缩的目录路径 + * @param {string} outputDir - 压缩文件输出目录 + * @returns {Promise} - 压缩文件的路径 + */ +async function createZipWithSystemCommand(sourceDir, outputDir) { + // 检查源目录 + if (!fs.existsSync(sourceDir)) { + throw new Error(`源目录不存在: ${sourceDir}`); + } + + // 生成文件名 + const dateString = new Date().toISOString().split('T')[0]; + const zipFileName = `mp-weixin-${dateString}-${new Date().getTime()}.zip`; + const zipFilePath = path.join(outputDir, zipFileName); + + let command; + + // 根据操作系统选择命令 + if (process.platform === 'win32') { + // Windows: 使用PowerShell的Compress-Archive + const sourcePath = sourceDir.replace(/'/g, "''"); + const destPath = zipFilePath.replace(/'/g, "''"); + command = `powershell -Command "Compress-Archive -Path '${sourcePath}\\*' -DestinationPath '${destPath}' -Force"`; + } else { + // Linux/Mac: 使用zip命令 + const sourceBase = path.dirname(sourceDir); + const sourceName = path.basename(sourceDir); + command = `cd '${sourceBase}' && zip -r '${zipFilePath}' '${sourceName}' -x '*/node_modules/*' '*.git/*' '*.DS_Store' '*.log'`; + } + + try { + console.log(`执行命令: ${command}`); + const { stdout, stderr } = await execAsync(command); + + if (stderr) { + console.warn('警告:', stderr); + } + + console.log(`✅ ZIP文件创建完成: ${zipFileName}`); + return zipFilePath; + } catch (error) { + throw new Error(`系统命令执行失败: ${error.message}`); + } +} + +module.exports = { + createZipWithSystemCommand +} \ No newline at end of file diff --git a/scripts/mp-weixin.patch.js b/scripts/mp-weixin.patch.js index 531b3f9..c3c0de9 100644 --- a/scripts/mp-weixin.patch.js +++ b/scripts/mp-weixin.patch.js @@ -20,9 +20,8 @@ const fs = require('fs'); const fsp = fs.promises; const path = require('path'); -const { exec } = require('child_process'); -const { promisify } = require('util'); -const execAsync = promisify(exec); +const { openFileDirectory } = require('./open-directory'); +const { createZipWithSystemCommand } = require('./create-zip'); async function commonPatch(mode = 'production') { try { @@ -97,52 +96,7 @@ async function commonPatch(mode = 'production') { } } -/** - * 使用系统命令创建ZIP(跨平台) - * @param {string} sourceDir - 要压缩的目录路径 - * @param {string} outputDir - 压缩文件输出目录 - * @returns {Promise} - 压缩文件的路径 - */ -async function createZipWithSystemCommand(sourceDir, outputDir) { - // 检查源目录 - if (!fs.existsSync(sourceDir)) { - throw new Error(`源目录不存在: ${sourceDir}`); - } - // 生成文件名 - const dateString = new Date().toISOString().split('T')[0]; - const zipFileName = `mp-weixin-${dateString}-${new Date().getTime()}.zip`; - const zipFilePath = path.join(outputDir, zipFileName); - - let command; - - // 根据操作系统选择命令 - if (process.platform === 'win32') { - // Windows: 使用PowerShell的Compress-Archive - const sourcePath = sourceDir.replace(/'/g, "''"); - const destPath = zipFilePath.replace(/'/g, "''"); - command = `powershell -Command "Compress-Archive -Path '${sourcePath}\\*' -DestinationPath '${destPath}' -Force"`; - } else { - // Linux/Mac: 使用zip命令 - const sourceBase = path.dirname(sourceDir); - const sourceName = path.basename(sourceDir); - command = `cd '${sourceBase}' && zip -r '${zipFilePath}' '${sourceName}' -x '*/node_modules/*' '*.git/*' '*.DS_Store' '*.log'`; - } - - try { - console.log(`执行命令: ${command}`); - const { stdout, stderr } = await execAsync(command); - - if (stderr) { - console.warn('警告:', stderr); - } - - console.log(`✅ ZIP文件创建完成: ${zipFileName}`); - return zipFilePath; - } catch (error) { - throw new Error(`系统命令执行失败: ${error.message}`); - } -} async function main() { // 1) 打补丁 @@ -155,6 +109,9 @@ async function main() { const destDir = path.join(cwd, 'unpackage', 'dist', 'build'); const zipFilePath = await createZipWithSystemCommand(sourceDir, destDir); console.log(`ZIP 文件路径: ${zipFilePath}`); + + // 3) 自动打开zip所在的目录 + await openFileDirectory(zipFilePath); } async function exists(p) { diff --git a/scripts/open-directory.js b/scripts/open-directory.js new file mode 100644 index 0000000..182c9ef --- /dev/null +++ b/scripts/open-directory.js @@ -0,0 +1,337 @@ +const { exec, spawn } = require('child_process'); +const { promisify } = require('util'); +const path = require('path'); +const fs = require('fs'); + +const execAsync = promisify(exec); + +/** + * 检测当前操作系统 + */ +function getOSPlatform() { + const platform = process.platform; + if (platform === 'win32') return 'windows'; + if (platform === 'darwin') return 'macos'; + if (platform === 'linux') return 'linux'; + return 'unknown'; +} + +/** + * 检查文件或目录是否存在 + */ +function checkPathExists(targetPath) { + try { + fs.accessSync(targetPath); + return true; + } catch (error) { + return false; + } +} + +/** + * 获取目录路径(如果是文件则返回所在目录) + */ +function getDirectoryPath(targetPath) { + try { + const stats = fs.statSync(targetPath); + if (stats.isFile()) { + return path.dirname(targetPath); + } + if (stats.isDirectory()) { + return targetPath; + } + } catch (error) { + throw new Error(`路径不存在或无法访问: ${targetPath}`); + } + return targetPath; +} + +/** + * 在 Windows 系统打开目录 + */ +async function openDirectoryWindows(directoryPath) { + // 确保路径使用反斜杠 + const normalizedPath = directoryPath.replace(/\//g, '\\'); + + console.log(`📁 在文件资源管理器中打开: ${normalizedPath}`); + + // 方法1: 使用 explorer 命令 + try { + const command = `explorer "${normalizedPath}"`; + await execAsync(command); + console.log('✅ 已启动文件资源管理器'); + return true; + } catch (error) { + console.warn('方法1失败:', error.message); + } + + // 方法2: 使用 start 命令 + try { + const command = `start "" "${normalizedPath}"`; + await execAsync(command); + console.log('✅ 已使用 start 命令打开'); + return true; + } catch (error) { + console.warn('方法2失败:', error.message); + } + + throw new Error('无法在Windows系统中打开目录'); +} + +/** + * 在 macOS 系统打开目录 + */ +async function openDirectoryMacOS(directoryPath) { + console.log(`📁 在访达中打开: ${directoryPath}`); + + // 方法1: 使用 open 命令 + try { + const command = `open "${directoryPath}"`; + await execAsync(command); + console.log('✅ 已启动访达'); + return true; + } catch (error) { + console.warn('方法1失败:', error.message); + } + + // 方法2: 使用 open -R 命令(打开包含指定文件的文件夹) + try { + const command = `open -R "${directoryPath}"`; + await execAsync(command); + console.log('✅ 已使用 open -R 命令打开'); + return true; + } catch (error) { + console.warn('方法2失败:', error.message); + } + + throw new Error('无法在macOS系统中打开目录'); +} + +/** + * 在 Linux 系统打开目录 + */ +async function openDirectoryLinux(directoryPath) { + console.log(`📁 在文件管理器中打开: ${directoryPath}`); + + // 尝试不同的文件管理器 + const fileManagers = [ + 'xdg-open', // 标准Linux桌面打开方式 + 'nautilus', // GNOME + 'dolphin', // KDE + 'thunar', // XFCE + 'pcmanfm', // LXDE + 'nemo', // Cinnamon + 'caja' // MATE + ]; + + for (const manager of fileManagers) { + try { + // 检查文件管理器是否可用 + await execAsync(`which ${manager}`); + + const command = `${manager} "${directoryPath}"`; + const child = spawn(manager, [directoryPath], { + stdio: 'ignore', + detached: true + }); + + child.unref(); + console.log(`✅ 已使用 ${manager} 打开目录`); + return true; + } catch (error) { + // 继续尝试下一个文件管理器 + continue; + } + } + + // 最后尝试 xdg-open(最通用的方式) + try { + const command = `xdg-open "${directoryPath}"`; + const child = spawn('xdg-open', [directoryPath], { + stdio: 'ignore', + detached: true + }); + + child.unref(); + console.log('✅ 已使用 xdg-open 打开目录'); + return true; + } catch (error) { + throw new Error('无法在Linux系统中打开目录,请确保已安装文件管理器'); + } +} + +/** + * 在终端中打开目录(跨平台) + */ +async function openDirectoryInTerminal(directoryPath) { + const os = getOSPlatform(); + const dirPath = getDirectoryPath(directoryPath); + + console.log(`💻 操作系统: ${os}`); + console.log(`📂 目标目录: ${dirPath}`); + + if (!checkPathExists(dirPath)) { + throw new Error(`路径不存在: ${dirPath}`); + } + + switch (os) { + case 'windows': + return await openDirectoryWindows(dirPath); + case 'macos': + return await openDirectoryMacOS(dirPath); + case 'linux': + return await openDirectoryLinux(dirPath); + default: + throw new Error(`不支持的操作系统: ${process.platform}`); + } +} + +/** + * 在系统默认终端中打开并切换到目录 + */ +async function openTerminalInDirectory(directoryPath) { + const os = getOSPlatform(); + const dirPath = getDirectoryPath(directoryPath); + + console.log(`🖥️ 在终端中打开目录: ${dirPath}`); + + if (!checkPathExists(dirPath)) { + throw new Error(`路径不存在: ${dirPath}`); + } + + const commands = { + windows: `start cmd /K "cd /d "${dirPath}" && echo 当前目录: %cd%"`, + macos: `osascript -e 'tell application "Terminal" to do script "cd \\\"${dirPath}\\\" && pwd"'`, + linux: `gnome-terminal --working-directory="${dirPath}" || konsole --workdir "${dirPath}" || xterm -e "cd \\"${dirPath}\\" && bash"` + }; + + try { + let command; + switch (os) { + case 'windows': + command = commands.windows; + break; + case 'macos': + command = commands.macos; + break; + case 'linux': + command = commands.linux; + break; + default: + throw new Error('不支持的操作系统'); + } + + // 使用 spawn 避免命令注入漏洞 + const shell = os === 'windows' ? 'cmd.exe' : '/bin/bash'; + const args = os === 'windows' ? ['/c', command] : ['-c', command]; + + const child = spawn(shell, args, { + stdio: 'ignore', + detached: true + }); + + child.unref(); + console.log('✅ 已启动终端并切换到目录'); + return true; + } catch (error) { + console.warn('无法在终端中打开目录:', error.message); + return false; + } +} + +/** + * 主函数 - 打开文件所在目录 + */ +async function openFileDirectory(filePath, options = {}) { + const { + openInTerminal = false, // 是否在终端中打开 + createIfNotExists = false, // 目录不存在时是否创建 + wait = false // 是否等待进程结束 + } = options; + + try { + // 检查路径是否存在 + if (!checkPathExists(filePath)) { + if (createIfNotExists) { + const dirPath = path.dirname(filePath); + fs.mkdirSync(dirPath, { recursive: true }); + console.log(`📁 创建目录: ${dirPath}`); + } else { + throw new Error(`路径不存在: ${filePath}`); + } + } + + const directoryPath = getDirectoryPath(filePath); + + if (openInTerminal) { + await openTerminalInDirectory(directoryPath); + } else { + await openDirectoryInTerminal(directoryPath); + } + + return true; + } catch (error) { + console.error('❌ 打开目录失败:', error.message); + return false; + } +} + +/** + * 使用示例 + */ +async function main() { + // 示例1: 打开当前脚本所在目录 + const currentFile = __filename; + console.log('当前文件:', currentFile); + + // 方法1: 在文件管理器中打开 + console.log('\n--- 在文件管理器中打开 ---'); + await openFileDirectory(currentFile); + + // 等待2秒 + await new Promise(resolve => setTimeout(resolve, 2000)); + + // 方法2: 在终端中打开(可选) + console.log('\n--- 在终端中打开 ---'); + await openFileDirectory(currentFile, { openInTerminal: true }); +} + +// 命令行使用方式 +if (require.main === module) { + const args = process.argv.slice(2); + + if (args.length === 0) { + // 没有参数,打开当前目录 + openFileDirectory(process.cwd()) + .then(success => { + if (!success) process.exit(1); + }) + .catch(error => { + console.error('错误:', error.message); + process.exit(1); + }); + } else { + const filePath = path.resolve(args[0]); + const options = { + openInTerminal: args.includes('--terminal') || args.includes('-t'), + createIfNotExists: args.includes('--create') || args.includes('-c') + }; + + openFileDirectory(filePath, options) + .then(success => { + if (!success) process.exit(1); + }) + .catch(error => { + console.error('错误:', error.message); + process.exit(1); + }); + } +} + +// 导出函数 +module.exports = { + openFileDirectory, + openDirectoryInTerminal, + openTerminalInDirectory, + getOSPlatform +}; \ No newline at end of file