201 lines
5.0 KiB
Vue
201 lines
5.0 KiB
Vue
<template>
|
|
<Dialog
|
|
v-model:visible="dialogVisible"
|
|
:modal="true"
|
|
:closable="!updateInfo?.forceUpdate"
|
|
header="发现新版本"
|
|
:style="{ width: '500px' }"
|
|
@hide="handleClose"
|
|
>
|
|
<div class="update-content">
|
|
<div class="update-info">
|
|
<p><strong>新版本号:</strong> {{ updateInfo?.version || '未知' }}</p>
|
|
<p v-if="updateInfo?.fileSize > 0"><strong>文件大小:</strong> {{ formatFileSize(updateInfo.fileSize) }}</p>
|
|
<div v-if="updateInfo?.releaseNotes" class="release-notes">
|
|
<p><strong>更新内容:</strong></p>
|
|
<pre>{{ updateInfo.releaseNotes }}</pre>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 下载进度 -->
|
|
<div v-if="isDownloading" class="update-progress">
|
|
<ProgressBar :value="updateProgress" />
|
|
<div class="progress-text">
|
|
<span>下载进度: {{ updateProgress }}%</span>
|
|
<span v-if="downloadState?.totalBytes > 0">
|
|
({{ formatFileSize(downloadState.downloadedBytes) }} / {{ formatFileSize(downloadState.totalBytes) }})
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<template #footer>
|
|
<Button
|
|
v-if="!isDownloading && updateProgress === 0"
|
|
label="立即更新"
|
|
@click="handleStartDownload"
|
|
/>
|
|
<Button
|
|
v-if="!isDownloading && updateProgress === 100"
|
|
label="立即安装"
|
|
@click="handleInstallUpdate"
|
|
/>
|
|
<Button
|
|
v-if="!updateInfo?.forceUpdate && !isDownloading && updateProgress === 0"
|
|
label="稍后提醒"
|
|
severity="secondary"
|
|
@click="handleClose"
|
|
/>
|
|
<Button
|
|
v-if="!updateInfo?.forceUpdate && !isDownloading && updateProgress === 100"
|
|
label="稍后安装"
|
|
severity="secondary"
|
|
@click="handleClose"
|
|
/>
|
|
</template>
|
|
</Dialog>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapState, mapActions } from 'vuex';
|
|
import { Dialog, Button, ProgressBar } from '../components/PrimeVue';
|
|
|
|
export default {
|
|
name: 'UpdateDialog',
|
|
components: {
|
|
Dialog,
|
|
Button,
|
|
ProgressBar
|
|
},
|
|
computed: {
|
|
...mapState('update', [
|
|
'updateDialogVisible',
|
|
'updateInfo',
|
|
'updateProgress',
|
|
'isDownloading',
|
|
'downloadState'
|
|
]),
|
|
dialogVisible: {
|
|
get() {
|
|
return this.updateDialogVisible && !!this.updateInfo;
|
|
},
|
|
set(value) {
|
|
if (!value) {
|
|
this.handleClose();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
methods: {
|
|
...mapActions('update', [
|
|
'hideUpdateDialog'
|
|
]),
|
|
handleClose() {
|
|
this.hideUpdateDialog();
|
|
},
|
|
async handleStartDownload() {
|
|
try {
|
|
const updateInfoData = this.updateInfo;
|
|
if (!updateInfoData) {
|
|
console.error('更新信息不存在');
|
|
return;
|
|
}
|
|
|
|
if (this.$store) {
|
|
this.$store.dispatch('update/setDownloading', true);
|
|
this.$store.dispatch('update/setUpdateProgress', 0);
|
|
}
|
|
|
|
if (!window.electronAPI || !window.electronAPI.update) {
|
|
throw new Error('Electron API不可用');
|
|
}
|
|
|
|
const result = await window.electronAPI.invoke('update:download', updateInfoData.downloadUrl);
|
|
|
|
if (!result.success) {
|
|
throw new Error(result.error || '下载失败');
|
|
}
|
|
} catch (error) {
|
|
console.error('开始下载更新失败:', error);
|
|
if (this.$store) {
|
|
this.$store.dispatch('update/setDownloading', false);
|
|
}
|
|
}
|
|
},
|
|
async handleInstallUpdate() {
|
|
try {
|
|
if (!window.electronAPI || !window.electronAPI.update) {
|
|
throw new Error('Electron API不可用');
|
|
}
|
|
|
|
if (this.$store) {
|
|
this.$store.dispatch('update/setDownloading', true);
|
|
}
|
|
|
|
const result = await window.electronAPI.invoke('update:install');
|
|
|
|
if (result.success) {
|
|
if (this.$store) {
|
|
this.$store.dispatch('update/hideUpdateDialog');
|
|
}
|
|
} else {
|
|
throw new Error(result.error || '安装失败');
|
|
}
|
|
} catch (error) {
|
|
console.error('安装更新失败:', error);
|
|
if (this.$store) {
|
|
this.$store.dispatch('update/setDownloading', false);
|
|
}
|
|
}
|
|
},
|
|
formatFileSize(bytes) {
|
|
if (!bytes || bytes === 0) return '0 B';
|
|
const k = 1024;
|
|
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.update-content {
|
|
padding: 10px 0;
|
|
}
|
|
|
|
.update-info {
|
|
margin-bottom: 20px;
|
|
|
|
p {
|
|
margin: 8px 0;
|
|
}
|
|
}
|
|
|
|
.release-notes {
|
|
margin-top: 15px;
|
|
|
|
pre {
|
|
background: #f5f5f5;
|
|
padding: 10px;
|
|
border-radius: 4px;
|
|
white-space: pre-wrap;
|
|
word-break: break-word;
|
|
font-size: 13px;
|
|
line-height: 1.5;
|
|
}
|
|
}
|
|
|
|
.update-progress {
|
|
margin-top: 20px;
|
|
|
|
.progress-text {
|
|
margin-top: 10px;
|
|
text-align: center;
|
|
font-size: 13px;
|
|
color: #666;
|
|
}
|
|
}
|
|
</style>
|
|
|