diff --git a/.github/workflows/dev-daily-fixed.yml b/.github/workflows/dev-daily-fixed.yml index e867f46..d84e1f0 100644 --- a/.github/workflows/dev-daily-fixed.yml +++ b/.github/workflows/dev-daily-fixed.yml @@ -95,7 +95,10 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash run: | - mapfile -t assets < <(find release -maxdepth 1 -type f | sort) + assets=() + while IFS= read -r file; do + assets+=("$file") + done < <(find release -maxdepth 1 -type f | sort) if [ "${#assets[@]}" -eq 0 ]; then echo "No release files found in ./release" exit 1 @@ -138,7 +141,10 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash run: | - mapfile -t assets < <(find release -maxdepth 1 -type f | sort) + assets=() + while IFS= read -r file; do + assets+=("$file") + done < <(find release -maxdepth 1 -type f | sort) if [ "${#assets[@]}" -eq 0 ]; then echo "No release files found in ./release" exit 1 @@ -181,7 +187,10 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash run: | - mapfile -t assets < <(find release -maxdepth 1 -type f | sort) + assets=() + while IFS= read -r file; do + assets+=("$file") + done < <(find release -maxdepth 1 -type f | sort) if [ "${#assets[@]}" -eq 0 ]; then echo "No release files found in ./release" exit 1 @@ -224,7 +233,10 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash run: | - mapfile -t assets < <(find release -maxdepth 1 -type f | sort) + assets=() + while IFS= read -r file; do + assets+=("$file") + done < <(find release -maxdepth 1 -type f | sort) if [ "${#assets[@]}" -eq 0 ]; then echo "No release files found in ./release" exit 1 diff --git a/electron/main.ts b/electron/main.ts index 355693a..a035c37 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -62,6 +62,60 @@ const getEffectiveUpdateTrack = (): 'stable' | 'preview' | 'dev' => { return configuredTrack || defaultUpdateTrack } +const isRemoteVersionNewer = (latestVersion: string, currentVersion: string): boolean => { + const latest = String(latestVersion || '').trim() + const current = String(currentVersion || '').trim() + if (!latest || !current) return false + + const parseVersion = (version: string) => { + const normalized = version.replace(/^v/i, '') + const [main, pre = ''] = normalized.split('-', 2) + const core = main.split('.').map((segment) => Number.parseInt(segment, 10) || 0) + const prerelease = pre ? pre.split('.').map((segment) => /^\d+$/.test(segment) ? Number.parseInt(segment, 10) : segment) : [] + return { core, prerelease } + } + + const compareParsedVersion = (a: ReturnType, b: ReturnType): number => { + const maxLen = Math.max(a.core.length, b.core.length) + for (let i = 0; i < maxLen; i += 1) { + const left = a.core[i] || 0 + const right = b.core[i] || 0 + if (left > right) return 1 + if (left < right) return -1 + } + + const aPre = a.prerelease + const bPre = b.prerelease + if (aPre.length === 0 && bPre.length === 0) return 0 + if (aPre.length === 0) return 1 + if (bPre.length === 0) return -1 + + const preMaxLen = Math.max(aPre.length, bPre.length) + for (let i = 0; i < preMaxLen; i += 1) { + const left = aPre[i] + const right = bPre[i] + if (left === undefined) return -1 + if (right === undefined) return 1 + if (left === right) continue + + const leftNum = typeof left === 'number' + const rightNum = typeof right === 'number' + if (leftNum && rightNum) return left > right ? 1 : -1 + if (leftNum) return -1 + if (rightNum) return 1 + return String(left) > String(right) ? 1 : -1 + } + + return 0 + } + + try { + return autoUpdater.currentVersion.compare(latest) < 0 + } catch { + return compareParsedVersion(parseVersion(latest), parseVersion(current)) > 0 + } +} + const applyAutoUpdateChannel = (reason: 'startup' | 'settings' = 'startup') => { const track = getEffectiveUpdateTrack() const baseUpdateChannel = track === 'stable' ? 'latest' : track @@ -1283,7 +1337,7 @@ function registerIpcHandlers() { if (result && result.updateInfo) { const currentVersion = app.getVersion() const latestVersion = result.updateInfo.version - if (latestVersion !== currentVersion) { + if (isRemoteVersionNewer(latestVersion, currentVersion)) { return { hasUpdate: true, version: latestVersion, @@ -2741,7 +2795,7 @@ function checkForUpdatesOnStartup() { const latestVersion = result.updateInfo.version // 检查是否有新版本 - if (latestVersion !== currentVersion && mainWindow) { + if (isRemoteVersionNewer(latestVersion, currentVersion) && mainWindow) { // 检查该版本是否被用户忽略 const ignoredVersion = configService?.get('ignoredUpdateVersion') if (ignoredVersion === latestVersion) { diff --git a/vite.config.ts b/vite.config.ts index d121f1b..04493f7 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -18,38 +18,6 @@ export default defineConfig({ chunkSizeWarningLimit: 900, commonjsOptions: { ignoreDynamicRequires: true - }, - rollupOptions: { - output: { - manualChunks(id) { - if (!id.includes('node_modules')) return - - if (id.includes('/react/') || id.includes('/react-dom/') || id.includes('/react-router')) { - return 'vendor-react' - } - - if (id.includes('/echarts') || id.includes('/echarts-for-react')) { - return 'vendor-echarts' - } - - if ( - id.includes('/react-markdown') || - id.includes('/remark-gfm') || - id.includes('/mdast-') || - id.includes('/micromark-') || - id.includes('/unified') || - id.includes('/vfile') - ) { - return 'vendor-markdown' - } - - if (id.includes('/jszip') || id.includes('/exceljs')) { - return 'vendor-export' - } - - return 'vendor-misc' - } - } } }, optimizeDeps: { @@ -204,6 +172,7 @@ export default defineConfig({ renderer() ], resolve: { + dedupe: ['react', 'react-dom'], alias: { '@': resolve(__dirname, 'src') }