200 lines
5.3 KiB
Vue
200 lines
5.3 KiB
Vue
<script setup lang="ts">
|
|
import { computed, onMounted, onUnmounted } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { useAppStore } from '@/renderer/store/app';
|
|
|
|
const { t } = useI18n();
|
|
const appStore = useAppStore();
|
|
|
|
// 从store获取状态
|
|
const updateStatus = computed(() => appStore.updateStatus);
|
|
const downloadProgress = computed(() => appStore.downloadProgress);
|
|
|
|
// 对话框显示状态
|
|
const dialogVisible = computed({
|
|
get: () => {
|
|
return appStore.updateDialogVisible
|
|
|| updateStatus.value.status === 'available'
|
|
|| updateStatus.value.status === 'downloading'
|
|
|| updateStatus.value.status === 'downloaded'
|
|
|| (updateStatus.value.status === 'error' && !!updateStatus.value.error);
|
|
},
|
|
set: (value: boolean) => {
|
|
if (value) {
|
|
appStore.showUpdateDialog();
|
|
} else {
|
|
appStore.hideUpdateDialog();
|
|
}
|
|
},
|
|
});
|
|
|
|
const latestVersion = computed(() => {
|
|
// 这里应该从API获取最新版本号,暂时使用固定值
|
|
return `v${(updateStatus.value.currentVersion || '1.0.0').replace(/^v?/, '').split('.').map((n, i) =>
|
|
i === 2 ? (Number.parseInt(n) + 1).toString() : n,
|
|
).join('.')}`;
|
|
});
|
|
|
|
const isDownloading = computed(() => updateStatus.value.status === 'downloading');
|
|
const isDownloadComplete = computed(() => downloadProgress.value >= 100);
|
|
|
|
// 方法
|
|
const downloadUpdate = async () => {
|
|
await appStore.startUpdateDownload();
|
|
};
|
|
|
|
const skipUpdate = () => {
|
|
appStore.setUpdateStatus('not-available', updateStatus.value.currentVersion);
|
|
dialogVisible.value = false;
|
|
};
|
|
|
|
const cancelDownload = () => {
|
|
// 取消下载逻辑
|
|
appStore.setUpdateStatus('not-available', updateStatus.value.currentVersion);
|
|
dialogVisible.value = false;
|
|
};
|
|
|
|
const laterInstall = () => {
|
|
dialogVisible.value = false;
|
|
};
|
|
|
|
const installUpdate = () => {
|
|
// 安装更新,这需要触发quitAndInstall
|
|
window.mainApi.invoke('msgInstallUpdate');
|
|
dialogVisible.value = false;
|
|
};
|
|
|
|
const closeDialog = () => {
|
|
appStore.setUpdateStatus('idle');
|
|
dialogVisible.value = false;
|
|
};
|
|
|
|
// 监听更新下载进度
|
|
onMounted(() => {
|
|
// 监听主进程发来的更新相关事件
|
|
window.mainApi.on('update-download-progress', (_, progress) => {
|
|
appStore.setDownloadProgress(progress.percent);
|
|
});
|
|
});
|
|
|
|
onUnmounted(() => {
|
|
// 移除事件监听器
|
|
window.mainApi.off('update-download-progress', () => {});
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<v-dialog
|
|
v-model="dialogVisible"
|
|
max-width="500"
|
|
persistent
|
|
:scrim="false"
|
|
>
|
|
<v-card v-if="updateStatus.status === 'available'">
|
|
<v-card-title class="headline">
|
|
{{ t('update.newVersionAvailable') }}
|
|
</v-card-title>
|
|
<v-card-text>
|
|
<div>{{ t('update.currentVersion') }}: {{ updateStatus.currentVersion }}</div>
|
|
<div>{{ t('update.latestVersion') }}: {{ latestVersion }}</div>
|
|
<div class="mt-3">
|
|
{{ t('update.updateDescription') }}
|
|
</div>
|
|
</v-card-text>
|
|
<v-card-actions>
|
|
<v-spacer />
|
|
<v-btn
|
|
color="primary"
|
|
variant="text"
|
|
@click="skipUpdate"
|
|
>
|
|
{{ t('update.skipUpdate') }}
|
|
</v-btn>
|
|
<v-btn
|
|
color="primary"
|
|
variant="flat"
|
|
:loading="isDownloading"
|
|
@click="downloadUpdate"
|
|
>
|
|
{{ t('update.downloadUpdate') }}
|
|
</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
|
|
<v-card v-else-if="updateStatus.status === 'downloading'">
|
|
<v-card-title class="headline">
|
|
{{ t('update.downloadingUpdate') }}
|
|
</v-card-title>
|
|
<v-card-text>
|
|
<v-progress-linear
|
|
:model-value="downloadProgress"
|
|
color="primary"
|
|
height="25"
|
|
rounded
|
|
>
|
|
<strong>{{ Math.round(downloadProgress) }}%</strong>
|
|
</v-progress-linear>
|
|
<div class="mt-3">
|
|
{{ t('update.downloadProgressText') }}
|
|
</div>
|
|
</v-card-text>
|
|
<v-card-actions>
|
|
<v-spacer />
|
|
<v-btn
|
|
color="primary"
|
|
variant="text"
|
|
:disabled="isDownloadComplete"
|
|
@click="cancelDownload"
|
|
>
|
|
{{ t('common.cancel') }}
|
|
</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
|
|
<v-card v-else-if="updateStatus.status === 'downloaded'">
|
|
<v-card-title class="headline">
|
|
{{ t('update.updateDownloaded') }}
|
|
</v-card-title>
|
|
<v-card-text>
|
|
{{ t('update.updateReadyToInstall') }}
|
|
</v-card-text>
|
|
<v-card-actions>
|
|
<v-spacer />
|
|
<v-btn
|
|
color="primary"
|
|
variant="text"
|
|
@click="laterInstall"
|
|
>
|
|
{{ t('update.laterInstall') }}
|
|
</v-btn>
|
|
<v-btn
|
|
color="primary"
|
|
variant="flat"
|
|
@click="installUpdate"
|
|
>
|
|
{{ t('update.installNow') }}
|
|
</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
|
|
<v-card v-else-if="updateStatus.status === 'error'">
|
|
<v-card-title class="headline">
|
|
{{ t('update.updateError') }}
|
|
</v-card-title>
|
|
<v-card-text>
|
|
{{ updateStatus.error }}
|
|
</v-card-text>
|
|
<v-card-actions>
|
|
<v-spacer />
|
|
<v-btn
|
|
color="primary"
|
|
variant="flat"
|
|
@click="closeDialog"
|
|
>
|
|
{{ t('common.ok') }}
|
|
</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
</v-dialog>
|
|
</template>
|