1
This commit is contained in:
200
app/components/UpdateDialog.vue
Normal file
200
app/components/UpdateDialog.vue
Normal file
@@ -0,0 +1,200 @@
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user