mac不强制更新

This commit is contained in:
2026-03-13 17:48:00 +08:00
parent 1dd64988ba
commit 44df456240
5 changed files with 218 additions and 87 deletions

View File

@@ -14,7 +14,8 @@
<!-- 配置页面 - 使用 v-show 保持状态 -->
<div class="h-full w-full animate-fadeIn" v-show="currentPage === 'config'">
<ConfigPage @go-to-browser="handleGoToBrowser" @logout="handleLogout" />
<UpdateNotification />
<!-- 更新通知组件启动时已在 UpdateChecker 检查此处暂不显示 -->
<!-- <UpdateNotification /> -->
</div>
<!-- 浏览器页面 -->

View File

@@ -38,10 +38,31 @@
<p v-if="updateInfo.releaseNotes" class="text-gray-500 text-xs bg-gray-50 p-2 rounded-lg line-clamp-3">
{{ updateInfo.releaseNotes }}
</p>
<!-- Mac 用户跳转下载页面 -->
<template v-if="isMac">
<p class="text-amber-600 text-sm bg-amber-50 p-2 rounded-lg">
Mac 版本请前往官网下载最新安装包
</p>
<div class="flex gap-2">
<button @click="openDownloadPage"
class="flex-1 py-2 bg-gradient-to-r from-blue-500 to-blue-600 text-white rounded-lg font-medium hover:from-blue-600 hover:to-blue-700 transition-all shadow-md hover:shadow-lg">
前往下载
</button>
<button @click="dismissUpdate"
class="px-4 py-2 bg-gray-100 text-gray-600 rounded-lg font-medium hover:bg-gray-200 transition-all">
稍后提醒
</button>
</div>
</template>
<!-- Windows 用户正常下载更新 -->
<template v-else>
<button @click="downloadUpdate"
class="w-full py-2 bg-gradient-to-r from-blue-500 to-blue-600 text-white rounded-lg font-medium hover:from-blue-600 hover:to-blue-700 transition-all shadow-md hover:shadow-lg">
下载更新
</button>
</template>
</div>
<!-- 下载中 -->
@@ -107,6 +128,7 @@ const {
progress,
error,
currentVersion,
isMac,
checkForUpdates,
downloadUpdate,
installUpdate,
@@ -120,4 +142,13 @@ function formatBytes(bytes) {
const i = Math.floor(Math.log(bytes) / Math.log(k))
return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`
}
// 打开下载页面
const openDownloadPage = () => {
if (isElectronEnv) {
window.electronAPI.openExternal?.('https://yolozs.com/')
} else {
window.open('https://yolozs.com/', '_blank')
}
}
</script>

View File

@@ -1,19 +1,50 @@
import { ref, onMounted, onUnmounted } from 'vue'
import { ref, onMounted, onUnmounted, computed } from 'vue'
import { isElectron } from '../utils/electronBridge'
// NOTE: Since we are using JS, we don't have interfaces, but structure remains same.
// ============== 单例状态 ==============
// 在函数外部定义,确保所有组件共享同一个状态
/**
* 应用更新 Hook (Vue Composable)
* 管理更新状态、进度和操作
* 注意:此 Composable 仅在 Electron 环境中有效
*/
export function useUpdate() {
const status = ref('idle')
const updateInfo = ref(null)
const progress = ref(null)
const error = ref(null)
const currentVersion = ref('')
const platform = ref('unknown')
let listenersSetup = false // 标记是否已设置监听器
let unsubList = [] // 取消订阅列表
const isMac = computed(() => platform.value === 'mac')
const isWindows = computed(() => platform.value === 'windows')
// 平台判断
const getPlatformInfo = () => {
const navPlatform = navigator.platform || ''
const ua = navigator.userAgent || ''
const appVersion = navigator.appVersion || ''
console.log('[useUpdate] 平台检测信息:', {
navPlatform,
userAgent: ua,
appVersion
})
const p = navPlatform.toLowerCase()
if (p.includes('mac')) return 'mac'
if (p.includes('win')) return 'windows'
if (p.includes('linux')) return 'linux'
const u = ua.toLowerCase()
if (u.includes('macintosh') || u.includes('mac os') || u.includes('macintel')) return 'mac'
if (u.includes('windows') || u.includes('win32') || u.includes('win64')) return 'windows'
if (u.includes('linux')) return 'linux'
const av = appVersion.toLowerCase()
if (av.includes('mac')) return 'mac'
if (av.includes('win')) return 'windows'
if (av.includes('linux')) return 'linux'
return 'unknown'
}
// 获取当前版本
const fetchVersion = () => {
@@ -26,12 +57,11 @@ export function useUpdate() {
}).catch(console.error)
}
let unsubList = []
// 监听更新事件
// 设置监听器(只执行一次)
const setupListeners = () => {
if (!isElectron()) return
if (!isElectron() || listenersSetup) return
listenersSetup = true
const api = window.electronAPI
// 正在检查
@@ -74,21 +104,38 @@ export function useUpdate() {
if (api.onUpdateManualInstall) {
unsubList.push(api.onUpdateManualInstall((info) => {
console.log('macOS 需要手动安装更新:', info.path)
// 显示提示让用户知道需要手动安装
alert(`更新已下载完成!\n\n请手动安装更新文件:\n${info.path}\n\n应用将退出。`)
}))
}
}
// 清理监听器
const cleanupListeners = () => {
unsubList.forEach(unsub => unsub && unsub())
unsubList = []
listenersSetup = false
}
/**
* 应用更新 Hook (Vue Composable)
* 单例模式:所有组件共享同一个状态和监听器
* 注意:此 Composable 仅在 Electron 环境中有效
*/
export function useUpdate() {
// 每个组件挂载时的初始化逻辑
onMounted(() => {
// 检测平台(确保只设置一次)
if (isElectron() && platform.value === 'unknown') {
platform.value = getPlatformInfo()
console.log('[useUpdate] 平台检测结果:', platform.value)
}
fetchVersion()
setupListeners()
})
onUnmounted(() => {
unsubList.forEach(unsub => unsub && unsub())
unsubList = []
})
// 注意:不在这里清理监听器,因为是单例模式
// 只在最后一个组件卸载时才清理(这里简化处理,不清理)
// 如果需要严格清理,可以使用引用计数
const checkForUpdates = () => {
if (!isElectron()) return
@@ -132,6 +179,9 @@ export function useUpdate() {
progress,
error,
currentVersion,
platform,
isMac,
isWindows,
checkForUpdates,
downloadUpdate,
installUpdate,

View File

@@ -76,10 +76,24 @@
<p class="text-gray-600 text-sm whitespace-pre-wrap">{{ updateInfo.releaseNotes }}</p>
</div>
<!-- Mac 用户跳转下载页面 -->
<template v-if="isMac">
<p class="text-amber-600 text-sm bg-amber-50 p-3 rounded-lg text-center">
Mac 版本请前往官网下载最新安装包
</p>
<button @click="openDownloadPage"
class="w-full py-3 bg-gradient-to-r from-blue-600 to-blue-500 text-white rounded-lg font-medium hover:from-blue-700 hover:to-blue-600 transition-all shadow-sm">
前往下载
</button>
</template>
<!-- Windows 用户正常下载更新 -->
<template v-else>
<button @click="downloadUpdate"
class="w-full py-3 bg-gradient-to-r from-blue-600 to-blue-500 text-white rounded-lg font-medium hover:from-blue-700 hover:to-blue-600 transition-all shadow-sm">
立即下载更新
</button>
</template>
<p class="text-center text-gray-400 text-xs">
必须更新后才能使用程序
@@ -185,6 +199,7 @@ const {
progress,
error,
currentVersion,
isMac,
checkForUpdates,
downloadUpdate,
installUpdate
@@ -304,6 +319,15 @@ function formatBytes(bytes) {
return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`
}
// 打开下载页面Mac 用户)
function openDownloadPage() {
if (isElectronEnv) {
window.electronAPI.openExternal?.('https://yolozs.com/')
} else {
window.open('https://yolozs.com/', '_blank')
}
}
onUnmounted(() => {
if (timeoutTimer) clearTimeout(timeoutTimer)
if (countdownTimer) clearInterval(countdownTimer)

View File

@@ -0,0 +1,25 @@
// vite.config.js
import { defineConfig } from "file:///D:/git/gitea/web-fusion/node_modules/vite/dist/node/index.js";
import vue from "file:///D:/git/gitea/web-fusion/node_modules/@vitejs/plugin-vue/dist/index.mjs";
import { resolve } from "path";
var __vite_injected_original_dirname = "D:\\git\\gitea\\web-fusion";
var vite_config_default = defineConfig({
plugins: [vue()],
resolve: {
alias: {
"@": resolve(__vite_injected_original_dirname, "src")
}
},
server: {
port: 5173,
host: true
},
build: {
outDir: "dist",
sourcemap: false
}
});
export {
vite_config_default as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJEOlxcXFxnaXRcXFxcZ2l0ZWFcXFxcd2ViLWZ1c2lvblwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiRDpcXFxcZ2l0XFxcXGdpdGVhXFxcXHdlYi1mdXNpb25cXFxcdml0ZS5jb25maWcuanNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL0Q6L2dpdC9naXRlYS93ZWItZnVzaW9uL3ZpdGUuY29uZmlnLmpzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSdcclxuaW1wb3J0IHZ1ZSBmcm9tICdAdml0ZWpzL3BsdWdpbi12dWUnXHJcbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tICdwYXRoJ1xyXG5cclxuLy8gaHR0cHM6Ly92aXRlanMuZGV2L2NvbmZpZy9cclxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcclxuICAgIHBsdWdpbnM6IFt2dWUoKV0sXHJcbiAgICByZXNvbHZlOiB7XHJcbiAgICAgICAgYWxpYXM6IHtcclxuICAgICAgICAgICAgJ0AnOiByZXNvbHZlKF9fZGlybmFtZSwgJ3NyYycpXHJcbiAgICAgICAgfVxyXG4gICAgfSxcclxuICAgIHNlcnZlcjoge1xyXG4gICAgICAgIHBvcnQ6IDUxNzMsXHJcbiAgICAgICAgaG9zdDogdHJ1ZVxyXG4gICAgfSxcclxuICAgIGJ1aWxkOiB7XHJcbiAgICAgICAgb3V0RGlyOiAnZGlzdCcsXHJcbiAgICAgICAgc291cmNlbWFwOiBmYWxzZVxyXG4gICAgfVxyXG59KVxyXG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQStQLFNBQVMsb0JBQW9CO0FBQzVSLE9BQU8sU0FBUztBQUNoQixTQUFTLGVBQWU7QUFGeEIsSUFBTSxtQ0FBbUM7QUFLekMsSUFBTyxzQkFBUSxhQUFhO0FBQUEsRUFDeEIsU0FBUyxDQUFDLElBQUksQ0FBQztBQUFBLEVBQ2YsU0FBUztBQUFBLElBQ0wsT0FBTztBQUFBLE1BQ0gsS0FBSyxRQUFRLGtDQUFXLEtBQUs7QUFBQSxJQUNqQztBQUFBLEVBQ0o7QUFBQSxFQUNBLFFBQVE7QUFBQSxJQUNKLE1BQU07QUFBQSxJQUNOLE1BQU07QUFBQSxFQUNWO0FBQUEsRUFDQSxPQUFPO0FBQUEsSUFDSCxRQUFRO0FBQUEsSUFDUixXQUFXO0FBQUEsRUFDZjtBQUNKLENBQUM7IiwKICAibmFtZXMiOiBbXQp9Cg==