From 812bc64b6f7a81a5c29bcca9e4f103a84cc4af75 Mon Sep 17 00:00:00 2001 From: purp1e Date: Sun, 9 Nov 2025 00:30:26 +0800 Subject: [PATCH] [feat] fullfil tasks to minify manual actions --- .vscode/tasks.json | 108 +++++++++++++++++++++-- next-env.d.ts | 2 +- package.json | 6 +- scripts/generate-latest-json.js | 49 ++++++++++- scripts/rename-build-artifacts.js | 142 ++++++++++++++++++++++++++++++ src-tauri/tauri.conf.json | 2 +- 6 files changed, 296 insertions(+), 13 deletions(-) create mode 100644 scripts/rename-build-artifacts.js diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 41cfc40..7d8cf3d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -4,19 +4,117 @@ "version": "2.0.0", "tasks": [ { - "label": "Dev Tauri", + "label": "🚀 Dev Tauri", "type": "shell", "command": "bun tauri dev", + "group": { + "kind": "build", + "isDefault": false + }, + "presentation": { + "reveal": "always", + "panel": "new" + } }, { - "label": "Build Tauri to nsis installer", + "label": "📦 Build: Release (NSIS)", "type": "shell", - "command": "bun tauri build -b nsis", + "command": "& .\\.tauri\\set-env.ps1; bun tauri build -b nsis", + "group": "build", + "presentation": { + "reveal": "always", + "panel": "new" + } }, { - "label": "Build Tauri", + "label": "📦 Build: Release (All)", "type": "shell", - "command": "bun tauri build", + "command": "& .\\.tauri\\set-env.ps1; bun tauri build", + "group": "build", + "presentation": { + "reveal": "always", + "panel": "new" + } + }, + { + "label": "⚡ Build: Fast (Dev Profile)", + "type": "shell", + "command": "& .\\.tauri\\set-env.ps1; bun tauri build -b nsis -- --profile dev", + "group": "build", + "presentation": { + "reveal": "always", + "panel": "new" + } + }, + { + "label": "⚡ Build: Fast Prod (Fast-Release Profile)", + "type": "shell", + "command": "& .\\.tauri\\set-env.ps1; bun tauri build -b nsis -- --profile fast-release", + "group": "build", + "presentation": { + "reveal": "always", + "panel": "new" + } + }, + { + "label": "📦 Build: Release + Rename + Gen Latest", + "type": "shell", + "command": "& .\\.tauri\\set-env.ps1; bun tauri build -b nsis; if ($LASTEXITCODE -eq 0) { node scripts/generate-latest-json.js --base-url https://github.com/plsgo/cstb/releases --rename }", + "group": "build", + "presentation": { + "reveal": "always", + "panel": "new" + } + }, + { + "label": "⚡ Build: Fast + Rename + Gen Latest", + "type": "shell", + "command": "& .\\.tauri\\set-env.ps1; bun tauri build -b nsis -- --profile dev; if ($LASTEXITCODE -eq 0) { node scripts/generate-latest-json.js --base-url https://github.com/plsgo/cstb/releases --target debug --rename }", + "group": "build", + "presentation": { + "reveal": "always", + "panel": "new" + } + }, + { + "label": "⚡ Build: Fast Prod + Rename + Gen Latest", + "type": "shell", + "command": "& .\\.tauri\\set-env.ps1; bun tauri build -b nsis -- --profile fast-release; if ($LASTEXITCODE -eq 0) { node scripts/generate-latest-json.js --base-url https://github.com/plsgo/cstb/releases --target fast-release --rename }", + "group": "build", + "presentation": { + "reveal": "always", + "panel": "new" + } + }, + { + "label": "🔄 Rename Build Artifacts", + "type": "shell", + "command": "node scripts/rename-build-artifacts.js --target release", + "group": "build", + "presentation": { + "reveal": "always", + "panel": "new" + } + }, + { + "label": "📄 Generate Latest JSON", + "type": "shell", + "command": "node scripts/generate-latest-json.js --base-url https://github.com/plsgo/cstb/releases", + "group": "build", + "presentation": { + "reveal": "always", + "panel": "new" + } + }, + { + "label": "📄 Generate Latest JSON (with Rename)", + "type": "shell", + "command": "node scripts/generate-latest-json.js --base-url https://github.com/plsgo/cstb/releases --rename", + "group": "build", + "presentation": { + "reveal": "always", + "panel": "new" + } } ] } \ No newline at end of file diff --git a/next-env.d.ts b/next-env.d.ts index c4b7818..9edff1c 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next/dev/types/routes.d.ts"; +import "./.next/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/package.json b/package.json index 25fdfb9..2e568c4 100644 --- a/package.json +++ b/package.json @@ -16,9 +16,9 @@ "dev": "tauri dev", "lint": "next lint", "fix": "next lint --fix", - "gen": "node scripts/generate-latest-json.js --base-url https://github.com/plsgo/cstb/releases", - "gen:debug": "node scripts/generate-latest-json.js --base-url https://github.com/plsgo/cstb/releases --target debug", - "gen:fast-release": "node scripts/generate-latest-json.js --base-url https://github.com/plsgo/cstb/releases --target fast-release" + "gen": "node scripts/generate-latest-json.js --base-url https://github.com/plsgo/cstb/releases --rename", + "gen:debug": "node scripts/generate-latest-json.js --base-url https://github.com/plsgo/cstb/releases --target debug --rename", + "gen:fast-release": "node scripts/generate-latest-json.js --base-url https://github.com/plsgo/cstb/releases --target fast-release --rename" }, "dependencies": { "@formkit/auto-animate": "^0.8.4", diff --git a/scripts/generate-latest-json.js b/scripts/generate-latest-json.js index 474c7ab..5879d2d 100644 --- a/scripts/generate-latest-json.js +++ b/scripts/generate-latest-json.js @@ -11,6 +11,7 @@ * --version 版本号(可选,默认从 tauri.conf.json 读取) * --notes 更新说明(可选) * --target 构建类型(可选,默认 release,可选值:debug、release、fast-release) + * --rename 在生成 latest.json 之前,将文件名中的 "CS工具箱" 改为 "CS_Toolbox" */ const fs = require('fs'); @@ -34,6 +35,7 @@ const version = getArg('--version', tauriConfig.version); const baseUrl = getArg('--base-url'); const notes = getArg('--notes', ''); const target = getArg('--target', 'release'); +const shouldRename = args.includes('--rename'); // 验证 target 参数 const validTargets = ['debug', 'release', 'fast-release']; @@ -48,6 +50,22 @@ if (!baseUrl) { process.exit(1); } +// 如果需要重命名,先执行重命名脚本 +if (shouldRename) { + console.log('\n执行文件重命名...'); + const { execSync } = require('child_process'); + try { + execSync(`node scripts/rename-build-artifacts.js --target ${target}`, { + stdio: 'inherit', + cwd: path.join(__dirname, '..') + }); + console.log('✓ 文件重命名完成\n'); + } catch (err) { + console.error('✗ 文件重命名失败:', err.message); + process.exit(1); + } +} + // 确保 baseUrl 不以 / 结尾 const cleanBaseUrl = baseUrl.replace(/\/$/, ''); @@ -63,13 +81,20 @@ if (githubReleasesMatch) { // 生成文件 URL function generateFileUrl(filename) { + // 如果使用了 --rename,文件名应该已经是 CS_Toolbox 了 + // 但为了兼容,我们检查一下是否需要替换 + let finalFilename = filename; + if (shouldRename && filename.includes('CS工具箱')) { + finalFilename = filename.replace(/CS工具箱/g, 'CS_Toolbox'); + } + if (githubOwner && githubRepo) { // GitHub releases 下载 URL 格式: https://github.com/{owner}/{repo}/releases/download/{tag}/{filename} const tag = version.startsWith('v') ? version : `v${version}`; - return `https://github.com/${githubOwner}/${githubRepo}/releases/download/${tag}/${filename}`; + return `https://github.com/${githubOwner}/${githubRepo}/releases/download/${tag}/${finalFilename}`; } // 普通 URL - return `${cleanBaseUrl}/${filename}`; + return `${cleanBaseUrl}/${finalFilename}`; } // 根据 target 确定构建产物目录 @@ -196,7 +221,25 @@ for (const [platform, config] of Object.entries(platforms)) { const result = findFiles(config.dir, version, config.extensions); if (result) { - console.log(` ✓ 找到文件: ${result.file}`); + // 如果使用了 --rename,文件名应该已经是 CS_Toolbox 了 + // 但如果仍然包含 CS工具箱,说明重命名可能失败了,尝试手动处理 + let fileName = result.file; + if (shouldRename && fileName.includes('CS工具箱')) { + console.warn(` 警告: 文件 ${fileName} 仍包含中文,尝试查找重命名后的文件...`); + const renamedFile = fileName.replace(/CS工具箱/g, 'CS_Toolbox'); + const renamedPath = path.join(config.dir, renamedFile); + if (fs.existsSync(renamedPath)) { + fileName = renamedFile; + result.file = renamedFile; + result.url = generateFileUrl(renamedFile); + // 检查重命名后的签名文件 + const renamedSigPath = renamedPath + '.sig'; + if (fs.existsSync(renamedSigPath)) { + result.signature = fs.readFileSync(renamedSigPath, 'utf-8').trim(); + } + } + } + console.log(` ✓ 找到文件: ${fileName}`); platformsData[platform] = { url: result.url, signature: result.signature diff --git a/scripts/rename-build-artifacts.js b/scripts/rename-build-artifacts.js new file mode 100644 index 0000000..7628de5 --- /dev/null +++ b/scripts/rename-build-artifacts.js @@ -0,0 +1,142 @@ +#!/usr/bin/env node + +/** + * 批量重命名构建产物,将文件名中的 "CS工具箱" 改为 "CS_Toolbox" + * 用于解决 GitHub releases 不支持中文文件名的问题 + * + * 使用方法: + * node scripts/rename-build-artifacts.js [options] + * + * 选项: + * --target 构建类型(可选,默认 release,可选值:debug、release、fast-release) + * --dry-run 仅显示将要重命名的文件,不实际执行 + */ + +const fs = require('fs'); +const path = require('path'); + +// 解析命令行参数 +const args = process.argv.slice(2); +const getArg = (name, defaultValue = null) => { + const index = args.indexOf(name); + if (index !== -1 && args[index + 1]) { + return args[index + 1]; + } + return defaultValue; +}; + +const target = getArg('--target', 'release'); +const dryRun = args.includes('--dry-run'); + +// 验证 target 参数 +const validTargets = ['debug', 'release', 'fast-release']; +if (!validTargets.includes(target)) { + console.error(`错误: --target 必须是以下值之一: ${validTargets.join(', ')}`); + process.exit(1); +} + +// 根据 target 确定构建产物目录 +const bundleDir = path.join(__dirname, '../src-tauri/target', target, 'bundle'); +console.log(`使用构建类型: ${target}`); +console.log(`构建产物目录: ${bundleDir}`); +console.log(dryRun ? '(仅预览模式,不会实际重命名)' : ''); + +if (!fs.existsSync(bundleDir)) { + console.error(`错误: 构建产物目录不存在: ${bundleDir}`); + console.error('请先构建应用'); + process.exit(1); +} + +// 需要重命名的文件扩展名 +const extensions = ['.exe', '.dmg', '.AppImage', '.deb', '.rpm', '.app.tar.gz', '.sig']; + +// 递归查找并重命名文件 +function renameFilesRecursive(dir, maxDepth = 3, currentDepth = 0) { + if (!fs.existsSync(dir) || currentDepth > maxDepth) { + return []; + } + + const renamedFiles = []; + + try { + const items = fs.readdirSync(dir); + + for (const item of items) { + const itemPath = path.join(dir, item); + const stat = fs.statSync(itemPath); + + if (stat.isFile()) { + // 检查文件名是否包含 "CS工具箱" + if (item.includes('CS工具箱')) { + const newName = item.replace(/CS工具箱/g, 'CS_Toolbox'); + const newPath = path.join(dir, newName); + + // 检查新文件名是否已存在 + if (fs.existsSync(newPath) && itemPath !== newPath) { + console.warn(` 警告: 目标文件已存在,跳过: ${newName}`); + continue; + } + + renamedFiles.push({ + oldPath: itemPath, + newPath: newPath, + oldName: item, + newName: newName + }); + } + } else if (stat.isDirectory() && currentDepth < maxDepth) { + // 递归查找子目录 + const subRenamed = renameFilesRecursive(itemPath, maxDepth, currentDepth + 1); + renamedFiles.push(...subRenamed); + } + } + } catch (err) { + console.error(`读取目录时出错 ${dir}:`, err.message); + } + + return renamedFiles; +} + +// 查找所有需要重命名的文件 +console.log('\n查找需要重命名的文件...'); +const filesToRename = renameFilesRecursive(bundleDir); + +if (filesToRename.length === 0) { + console.log('✓ 未找到需要重命名的文件'); + process.exit(0); +} + +// 显示将要重命名的文件 +console.log(`\n找到 ${filesToRename.length} 个文件需要重命名:\n`); +filesToRename.forEach(({ oldName, newName }) => { + console.log(` ${oldName}`); + console.log(` → ${newName}\n`); +}); + +if (dryRun) { + console.log('(预览模式,未实际执行重命名)'); + process.exit(0); +} + +// 执行重命名 +console.log('执行重命名...'); +let successCount = 0; +let errorCount = 0; + +for (const { oldPath, newPath, oldName, newName } of filesToRename) { + try { + fs.renameSync(oldPath, newPath); + console.log(`✓ ${oldName} → ${newName}`); + successCount++; + } catch (err) { + console.error(`✗ 重命名失败 ${oldName}:`, err.message); + errorCount++; + } +} + +console.log(`\n完成: 成功 ${successCount} 个,失败 ${errorCount} 个`); + +if (errorCount > 0) { + process.exit(1); +} + diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 33803f6..7543a60 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -52,7 +52,7 @@ }, "productName": "CS工具箱", "mainBinaryName": "cstb", - "version": "0.0.6-beta.6", + "version": "0.0.6-beta.9", "identifier": "upup.cool", "plugins": { "deep-link": {