233 lines
8.4 KiB
Vue
233 lines
8.4 KiB
Vue
<template>
|
||
<div v-if="showButton" class="common-app-down" :class="{'on-client': $Electron}" :data-route="$route.name">
|
||
<div v-if="$Electron" class="common-app-down-link" @click="releasesNotification">
|
||
<Icon type="md-download"/> {{$L(repoTitle)}}
|
||
</div>
|
||
<a v-else class="common-app-down-link" :href="releases.html_url" target="_blank">
|
||
<Icon type="md-download"/> {{$L(repoTitle)}}
|
||
</a>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import Vue from 'vue'
|
||
import MarkdownPreview from "./MDEditor/components/preview";
|
||
import axios from "axios";
|
||
Vue.component('MarkdownPreview', MarkdownPreview)
|
||
|
||
import { Notification } from 'element-ui';
|
||
|
||
export default {
|
||
name: 'AppDown',
|
||
data() {
|
||
return {
|
||
repoName: 'kuaifan/dootask',
|
||
repoData: {},
|
||
|
||
status: 0, // 0 没有,1有客户端,2客户端有新版本
|
||
releases: {},
|
||
downInfo: {}
|
||
}
|
||
},
|
||
mounted() {
|
||
this.getReleases();
|
||
//
|
||
if (this.$Electron) {
|
||
this.$Electron.ipcRenderer.on('downloadDone', (event, args) => {
|
||
if (args.name == this.repoData.name) {
|
||
this.downInfo = args;
|
||
this.releasesNotification()
|
||
}
|
||
})
|
||
}
|
||
},
|
||
computed: {
|
||
repoTitle() {
|
||
return this.status == 2 ? '更新客户端' : '客户端下载';
|
||
},
|
||
showButton() {
|
||
return this.status && !this.$store.state.windowMax768 && ['login', 'manage-dashboard'].includes(this.$route.name)
|
||
}
|
||
},
|
||
methods: {
|
||
compareVersion(version1, version2) {
|
||
let pA = 0, pB = 0;
|
||
// 寻找当前区间的版本号
|
||
const findDigit = (str, start) => {
|
||
let i = start;
|
||
while (str[i] !== '.' && i < str.length) {
|
||
i++;
|
||
}
|
||
return i;
|
||
}
|
||
|
||
while (pA < version1.length && pB < version2.length) {
|
||
const nextA = findDigit(version1, pA);
|
||
const nextB = findDigit(version2, pB);
|
||
const numA = +version1.substr(pA, nextA - pA);
|
||
const numB = +version2.substr(pB, nextB - pB);
|
||
if (numA !== numB) {
|
||
return numA > numB ? 1 : -1;
|
||
}
|
||
pA = nextA + 1;
|
||
pB = nextB + 1;
|
||
}
|
||
// 若arrayA仍有小版本号
|
||
while (pA < version1.length) {
|
||
const nextA = findDigit(version1, pA);
|
||
const numA = +version1.substr(pA, nextA - pA);
|
||
if (numA > 0) {
|
||
return 1;
|
||
}
|
||
pA = nextA + 1;
|
||
}
|
||
// 若arrayB仍有小版本号
|
||
while (pB < version2.length) {
|
||
const nextB = findDigit(version2, pB);
|
||
const numB = +version2.substr(pB, nextB - pB);
|
||
if (numB > 0) {
|
||
return -1;
|
||
}
|
||
pB = nextB + 1;
|
||
}
|
||
// 版本号完全相同
|
||
return 0;
|
||
},
|
||
|
||
getReleases() {
|
||
if (this.status > 0) {
|
||
return;
|
||
}
|
||
//
|
||
let cache = $A.getStorageJson("cacheAppdown");
|
||
let timeout = 1800;
|
||
if (cache.time && cache.time + timeout > Math.round(new Date().getTime() / 1000)) {
|
||
this.releases = cache.data;
|
||
this.chackReleases()
|
||
return;
|
||
}
|
||
//
|
||
;(() => {
|
||
axios
|
||
.get("https://api.github.com/repos/" + this.repoName + "/releases/latest")
|
||
.then(({status, data}) => {
|
||
if (status === 200) {
|
||
$A.setStorage("cacheAppdown", {
|
||
time: Math.round(new Date().getTime() / 1000),
|
||
data: data
|
||
});
|
||
this.releases = data;
|
||
this.chackReleases();
|
||
setTimeout(this.getReleases, timeout)
|
||
}
|
||
});
|
||
})();
|
||
},
|
||
|
||
chackReleases() {
|
||
let hostName = $A.getDomain(window.systemInfo.apiUrl);
|
||
if (hostName == "" || hostName == '127.0.0.1') {
|
||
hostName = "public"
|
||
}
|
||
if (this.$Electron) {
|
||
// 客户端(更新)
|
||
let match = (window.navigator.userAgent + "").match(/\s+(Main|Sub)TaskWindow\/(.*?)\/(.*?)\//)
|
||
if (!match) {
|
||
return;
|
||
}
|
||
let artifactName = null;
|
||
if (match[2] === 'darwin') {
|
||
artifactName = `${hostName}-${this.releases.tag_name}-mac-${match[3]}.pkg`;
|
||
} else if (match[2] === 'win32') {
|
||
artifactName = `${hostName}-${this.releases.tag_name}-win-${match[3]}.exe`;
|
||
} else {
|
||
return;
|
||
}
|
||
this.repoData = (this.releases.assets || []).find(({name}) => name == artifactName);
|
||
if (!this.repoData) {
|
||
return;
|
||
}
|
||
let currentVersion = window.systemInfo.version;
|
||
let latestVersion = $A.leftDelete(this.releases.tag_name.toLowerCase(), "v")
|
||
if (this.compareVersion(latestVersion, currentVersion) === 1) {
|
||
// 有新版本
|
||
console.log("New version: " + latestVersion);
|
||
this.$Electron.ipcRenderer.send('downloadFile', {
|
||
url: this.repoData.browser_download_url
|
||
});
|
||
}
|
||
} else {
|
||
// 网页版(提示有客户端下载)
|
||
this.repoData = (this.releases.assets || []).find(({name}) => $A.strExists(name, hostName));
|
||
if (this.repoData) {
|
||
let latestVersion = $A.leftDelete(this.releases.tag_name.toLowerCase(), "v")
|
||
console.log("Exist client: " + latestVersion);
|
||
this.status = 1;
|
||
}
|
||
}
|
||
},
|
||
|
||
releasesNotification() {
|
||
if (this.downInfo.state != "completed") {
|
||
return;
|
||
}
|
||
const h = this.$createElement;
|
||
window.__appNotification && window.__appNotification.close();
|
||
window.__appNotification = Notification({
|
||
title: this.$L("更新提示"),
|
||
duration: 0,
|
||
position: "bottom-right",
|
||
customClass: "common-app-down-notification",
|
||
onClose: () => {
|
||
this.status = 2;
|
||
},
|
||
message: h('span', [
|
||
h('span', [
|
||
h('span', this.$L('发现新版本') + ": "),
|
||
h('Tag', {
|
||
props: {
|
||
color: 'volcano'
|
||
}
|
||
}, this.releases.tag_name)
|
||
]),
|
||
h('MarkdownPreview', {
|
||
class: 'common-app-down-body',
|
||
props: {
|
||
initialValue: this.releases.body
|
||
}
|
||
}),
|
||
h('div', {
|
||
class: 'common-app-down-link',
|
||
on: {
|
||
click: () => {
|
||
this.installApplication();
|
||
}
|
||
},
|
||
}, [
|
||
h('Icon', {
|
||
props: {
|
||
type: 'md-checkmark-circle-outline'
|
||
},
|
||
style: {
|
||
marginRight: '5px'
|
||
}
|
||
}),
|
||
h('span', this.$L('立即更新'))
|
||
]),
|
||
])
|
||
});
|
||
},
|
||
|
||
installApplication() {
|
||
if (!this.$Electron) {
|
||
return;
|
||
}
|
||
this.$Electron.ipcRenderer.send('openFile', {
|
||
path: this.downInfo.savePath
|
||
});
|
||
this.$Electron.ipcRenderer.send('windowQuit');
|
||
}
|
||
}
|
||
};
|
||
</script>
|