✨ Add update service
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
LanguageType,
|
||||
SystemThemeType,
|
||||
TabType,
|
||||
UpdatesConfig,
|
||||
} from '@/../bindings/voidraft/internal/models/models';
|
||||
import {useI18n} from 'vue-i18n';
|
||||
import {ConfigUtils} from '@/utils/configUtils';
|
||||
@@ -42,6 +43,10 @@ type AppearanceConfigKeyMap = {
|
||||
readonly [K in keyof AppearanceConfig]: string;
|
||||
};
|
||||
|
||||
type UpdatesConfigKeyMap = {
|
||||
readonly [K in keyof UpdatesConfig]: string;
|
||||
};
|
||||
|
||||
type NumberConfigKey = 'fontSize' | 'tabSize' | 'lineHeight';
|
||||
|
||||
// 配置键映射
|
||||
@@ -70,6 +75,11 @@ const APPEARANCE_CONFIG_KEY_MAP: AppearanceConfigKeyMap = {
|
||||
systemTheme: 'appearance.systemTheme'
|
||||
} as const;
|
||||
|
||||
const UPDATES_CONFIG_KEY_MAP: UpdatesConfigKeyMap = {
|
||||
version: 'updates.version',
|
||||
autoUpdate: 'updates.autoUpdate'
|
||||
} as const;
|
||||
|
||||
// 配置限制
|
||||
const CONFIG_LIMITS = {
|
||||
fontSize: {min: 12, max: 28, default: 13},
|
||||
@@ -145,7 +155,6 @@ const DEFAULT_CONFIG: AppConfig = {
|
||||
updates: {
|
||||
version: "1.0.0",
|
||||
autoUpdate: true,
|
||||
betaChannel: false
|
||||
},
|
||||
metadata: {
|
||||
version: '1.0.0',
|
||||
@@ -216,6 +225,21 @@ export const useConfigStore = defineStore('config', () => {
|
||||
state.config.appearance[key] = value;
|
||||
};
|
||||
|
||||
const updateUpdatesConfig = async <K extends keyof UpdatesConfig>(key: K, value: UpdatesConfig[K]): Promise<void> => {
|
||||
// 确保配置已加载
|
||||
if (!state.configLoaded && !state.isLoading) {
|
||||
await initConfig();
|
||||
}
|
||||
|
||||
const backendKey = UPDATES_CONFIG_KEY_MAP[key];
|
||||
if (!backendKey) {
|
||||
throw new Error(`No backend key mapping found for updates.${key.toString()}`);
|
||||
}
|
||||
|
||||
await ConfigService.Set(backendKey, value);
|
||||
state.config.updates[key] = value;
|
||||
};
|
||||
|
||||
// 加载配置
|
||||
const initConfig = async (): Promise<void> => {
|
||||
if (state.isLoading) return;
|
||||
@@ -411,6 +435,9 @@ export const useConfigStore = defineStore('config', () => {
|
||||
await updateGeneralConfig('startAtLogin', value);
|
||||
// 再调用系统设置API
|
||||
await StartupService.SetEnabled(value);
|
||||
}
|
||||
},
|
||||
|
||||
// 更新配置相关方法
|
||||
setAutoUpdate: async (value: boolean) => await updateUpdatesConfig('autoUpdate', value)
|
||||
};
|
||||
});
|
81
frontend/src/stores/updateStore.ts
Normal file
81
frontend/src/stores/updateStore.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import {defineStore} from 'pinia'
|
||||
import {computed, ref} from 'vue'
|
||||
import {CheckForUpdates} from '@/../bindings/voidraft/internal/services/updateservice'
|
||||
import {UpdateCheckResult} from '@/../bindings/voidraft/internal/services/models'
|
||||
import {useConfigStore} from './configStore'
|
||||
|
||||
export const useUpdateStore = defineStore('update', () => {
|
||||
// 状态
|
||||
const isChecking = ref(false)
|
||||
const updateResult = ref<UpdateCheckResult | null>(null)
|
||||
const hasCheckedOnStartup = ref(false)
|
||||
|
||||
// 计算属性
|
||||
const hasUpdate = computed(() => updateResult.value?.hasUpdate || false)
|
||||
const errorMessage = computed(() => updateResult.value?.error || '')
|
||||
|
||||
// 检查更新
|
||||
const checkForUpdates = async (): Promise<boolean> => {
|
||||
if (isChecking.value) return false
|
||||
|
||||
isChecking.value = true
|
||||
try {
|
||||
const result = await CheckForUpdates()
|
||||
updateResult.value = result
|
||||
return !result.error
|
||||
} catch (error) {
|
||||
updateResult.value = new UpdateCheckResult({
|
||||
hasUpdate: false,
|
||||
currentVer: '1.0.0',
|
||||
latestVer: '',
|
||||
releaseNotes: '',
|
||||
releaseURL: '',
|
||||
error: 'Network error'
|
||||
})
|
||||
return false
|
||||
} finally {
|
||||
isChecking.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 启动时检查更新
|
||||
const checkOnStartup = async () => {
|
||||
if (hasCheckedOnStartup.value) return
|
||||
const configStore = useConfigStore()
|
||||
|
||||
if (configStore.config.updates.autoUpdate) {
|
||||
await checkForUpdates()
|
||||
}
|
||||
hasCheckedOnStartup.value = true
|
||||
}
|
||||
|
||||
// 打开发布页面
|
||||
const openReleaseURL = () => {
|
||||
if (updateResult.value?.releaseURL) {
|
||||
window.open(updateResult.value.releaseURL, '_blank')
|
||||
}
|
||||
}
|
||||
|
||||
// 重置状态
|
||||
const reset = () => {
|
||||
updateResult.value = null
|
||||
isChecking.value = false
|
||||
}
|
||||
|
||||
return {
|
||||
// 状态
|
||||
isChecking,
|
||||
updateResult,
|
||||
hasCheckedOnStartup,
|
||||
|
||||
// 计算属性
|
||||
hasUpdate,
|
||||
errorMessage,
|
||||
|
||||
// 方法
|
||||
checkForUpdates,
|
||||
checkOnStartup,
|
||||
openReleaseURL,
|
||||
reset
|
||||
}
|
||||
})
|
Reference in New Issue
Block a user