From 2a8e030fb46cb0d55baf3a1dd40574e329cd4ebb Mon Sep 17 00:00:00 2001 From: kuaifan Date: Sat, 15 Jan 2022 23:36:21 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E5=AE=A2=E6=88=B7?= =?UTF-8?q?=E7=AB=AF=E8=87=AA=E5=8A=A8=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- electron/main.js | 117 ++++++++++-------- electron/utils.js | 17 +++ resources/assets/js/components/AppDown.vue | 65 +++++----- .../assets/sass/components/app-down.scss | 3 +- 4 files changed, 117 insertions(+), 85 deletions(-) diff --git a/electron/main.js b/electron/main.js index 6eabb198..246baefd 100644 --- a/electron/main.js +++ b/electron/main.js @@ -14,7 +14,7 @@ let mainWindow = null, devloadUrl = "", devloadCachePath = path.resolve(__dirname, ".devload"), downloadList = [], - downloadCacheFile = path.join(app.getPath('cache'), config.name + '.downloadCache'); + downloadCacheFile = path.join(app.getPath('cache'), config.name, '.downloadCache'); if (fs.existsSync(devloadCachePath)) { devloadUrl = fs.readFileSync(devloadCachePath, 'utf8') @@ -23,6 +23,39 @@ if (fs.existsSync(downloadCacheFile)) { downloadList = utils.jsonParse(fs.readFileSync(downloadCacheFile, 'utf8'), []) } +function downloadUpdate(item) { + const chain = item.getURLChain() + if (chain.length == 0) { + return + } + let currentState = item.getState() + if (currentState == "progressing" && item.isPaused()) { + currentState = "paused" + } + // + const downloadItem = downloadList.find(item => item.url == chain[0]) + if (downloadItem && downloadItem.state != currentState) { + downloadItem.state = currentState; + downloadItem.result = { + url: item.getURL(), + name: item.getFilename(), + savePath: item.getSavePath(), + mimeType: item.getMimeType(), + totalBytes: item.getTotalBytes(), + chain, + }; + fs.writeFileSync(downloadCacheFile, utils.jsonStringify(downloadList), 'utf8'); + // + if (currentState == 'completed') { + mainWindow.webContents.send("downloadDone", downloadItem) + log.info("下载完成", downloadItem) + } else { + mainWindow.webContents.send("downloadUpdate", downloadItem) + log.info("下载更新", downloadItem) + } + } +} + function createMainWindow() { mainWindow = new BrowserWindow({ width: 1280, @@ -69,37 +102,12 @@ function createMainWindow() { }) mainWindow.webContents.session.on('will-download', (event, item) => { - item.setSavePath(path.join(app.getPath('cache'), item.getFilename())); - item.on('done', (event, state) => { - try { - const info = { - state, - name: item.getFilename(), - url: item.getURL(), - chain: item.getURLChain(), - savePath: item.getSavePath(), - mimeType: item.getMimeType(), - totalBytes: item.getTotalBytes(), - }; - mainWindow.webContents.send("downloadDone", info) - // - if (info.state == "completed") { - // 下载完成 - info.chain.some(url => { - let download = downloadList.find(item => item.url == url) - if (download) { - download.status = "completed" - download.info = info - } - }) - fs.writeFileSync(downloadCacheFile, utils.jsonStringify(downloadList), 'utf8'); - } else { - // 下载失败 - info.chain.some(url => { - downloadList = downloadList.filter(item => item.url != url) - }) - } - } catch (e) { } + item.setSavePath(path.join(app.getPath('cache'), config.name, item.getFilename())); + item.on('updated', () => { + downloadUpdate(item) + }) + item.on('done', () => { + downloadUpdate(item) }) }) } @@ -201,26 +209,33 @@ ipcMain.on('inheritClose', (event) => { * @param args {url} */ ipcMain.on('downloadFile', (event, args) => { - const download = downloadList.find(({url}) => url == args.url); - if (download) { - if (download.status == "completed") { - if (fs.existsSync(download.info.savePath)) { - log.warn("已下载完成", args) - mainWindow.webContents.send("downloadDone", download.info) - } else { - log.info("开始重新下载", args) - download.status = "progressing" - mainWindow.webContents.downloadURL(args.url); - } - } else { - log.warn("已在下载列表中", args) - } - } else { - log.info("开始下载", args) - downloadList.push(Object.assign(args, { status: "progressing" })) - mainWindow.webContents.downloadURL(args.url); - } event.returnValue = "ok" + // + let appendJson = {state: "progressing", startTime: utils.Time()} + let downloadItem = downloadList.find(({url}) => url == args.url) + if (downloadItem) { + switch (downloadItem.state) { + case "completed": + if (fs.existsSync(downloadItem.result.savePath)) { // 下载完成,文件存在 + log.info("下载已完成", downloadItem) + mainWindow.webContents.send("downloadDone", downloadItem) + return + } + break; + case "progressing": + if (downloadItem.startTime + 480 > utils.Time()) { // 下载中,未超时(超时时间8分钟) + log.info("下载已存在", downloadItem) + return; + } + break; + } + downloadItem = Object.assign(downloadItem, appendJson) + } else { + downloadList.push(downloadItem = Object.assign(args, appendJson)) + } + fs.writeFileSync(downloadCacheFile, utils.jsonStringify(downloadList), 'utf8'); + mainWindow.webContents.downloadURL(downloadItem.url); + log.info("下载开始", downloadItem) }) /** diff --git a/electron/utils.js b/electron/utils.js index 70286e93..ca1507c9 100644 --- a/electron/utils.js +++ b/electron/utils.js @@ -252,4 +252,21 @@ module.exports = { let domain = (weburl + "").match(urlReg); return ((domain != null && domain.length > 0) ? domain[2] : ""); }, + + /** + * 返回10位数时间戳 + * @param v + * @returns {number} + * @constructor + */ + Time(v = undefined) { + let time + if (typeof v === "string" && this.strExists(v, "-")) { + v = v.replace(/-/g, '/'); + time = new Date(v).getTime(); + } else { + time = new Date().getTime(); + } + return Math.round(time / 1000) + }, } diff --git a/resources/assets/js/components/AppDown.vue b/resources/assets/js/components/AppDown.vue index 67672b07..6fb95964 100644 --- a/resources/assets/js/components/AppDown.vue +++ b/resources/assets/js/components/AppDown.vue @@ -3,7 +3,7 @@ - + {{$L(repoTitle)}} @@ -15,7 +15,6 @@ import MarkdownPreview from "./MDEditor/components/preview"; import axios from "axios"; Vue.component('MarkdownPreview', MarkdownPreview) -import {Store} from "le5le-store"; import {mapState} from "vuex"; export default { @@ -26,19 +25,19 @@ export default { repoName: 'kuaifan/dootask', repoData: {}, + repoStatus: 0, // 0 没有,1有客户端,2客户端有新版本 + repoReleases: {}, - status: 0, // 0 没有,1有客户端,2客户端有新版本 - releases: {}, - downInfo: {}, + downloadResult: {}, } }, mounted() { this.getReleases(); // if (this.$Electron) { - this.$Electron.ipcRenderer.on('downloadDone', (event, args) => { - if (args.name == this.repoData.name) { - this.downInfo = args; + this.$Electron.ipcRenderer.on('downloadDone', (event, {result}) => { + if (result.name == this.repoData.name) { + this.downloadResult = result; this.releasesNotification() } }) @@ -49,10 +48,10 @@ export default { 'wsOpenNum', ]), repoTitle() { - return this.status == 2 ? '更新客户端' : '客户端下载'; + return this.repoStatus == 2 ? '更新客户端' : '客户端下载'; }, showButton() { - return this.status && !this.$store.state.windowMax768 && ['login', 'manage-dashboard'].includes(this.$route.name) + return this.repoStatus && !this.$store.state.windowMax768 && ['login', 'manage-dashboard'].includes(this.$route.name) } }, watch: { @@ -108,7 +107,7 @@ export default { }, getReleases() { - if (this.status > 0) { + if (this.repoStatus > 0) { return; } if (this.loadIng > 0) { @@ -116,10 +115,11 @@ export default { } // let cache = $A.getStorageJson("cacheAppdown"); - let timeout = 1800; + let timeout = 600; if (cache.time && cache.time + timeout > Math.round(new Date().getTime() / 1000)) { - this.releases = cache.data; + this.repoReleases = cache.data; this.chackReleases() + setTimeout(this.getReleases, timeout * 1000) return; } // @@ -127,22 +127,24 @@ export default { axios.get("https://api.github.com/repos/" + this.repoName + "/releases/latest").then(({status, data}) => { this.loadIng--; if (status === 200) { - $A.setStorage("cacheAppdown", { + cache = { time: Math.round(new Date().getTime() / 1000), data: data - }); - this.releases = data; - this.chackReleases(); - setTimeout(this.getReleases, timeout) + } + $A.setStorage("cacheAppdown", cache); + this.repoReleases = cache.data; + this.chackReleases() } + setTimeout(this.getReleases, timeout * 1000) }).catch(() => { this.loadIng--; + setTimeout(this.getReleases, timeout * 1000) }); }, chackReleases() { let hostName = $A.getDomain(window.systemInfo.apiUrl); - if (hostName == "" || hostName == '127.0.0.1') { + if (hostName == "" || $A.leftExists(hostName, '127.0.0.1')) { hostName = "public" } if (this.$Electron) { @@ -153,18 +155,18 @@ export default { } let artifactName = null; if (match[2] === 'darwin') { - artifactName = `${hostName}-${this.releases.tag_name}-mac-${match[3]}.pkg`; + artifactName = `${hostName}-${this.repoReleases.tag_name}-mac-${match[3]}.pkg`; } else if (match[2] === 'win32') { - artifactName = `${hostName}-${this.releases.tag_name}-win-${match[3]}.exe`; + artifactName = `${hostName}-${this.repoReleases.tag_name}-win-${match[3]}.exe`; } else { return; } - this.repoData = (this.releases.assets || []).find(({name}) => name == artifactName); + this.repoData = (this.repoReleases.assets || []).find(({name}) => name == artifactName); if (!this.repoData) { return; } let currentVersion = window.systemInfo.version; - let latestVersion = $A.leftDelete(this.releases.tag_name.toLowerCase(), "v") + let latestVersion = $A.leftDelete(this.repoReleases.tag_name.toLowerCase(), "v") if (this.compareVersion(latestVersion, currentVersion) === 1) { // 有新版本 console.log("New version: " + latestVersion); @@ -174,26 +176,23 @@ export default { } } else { // 网页版(提示有客户端下载) - this.repoData = (this.releases.assets || []).find(({name}) => $A.strExists(name, hostName)); + this.repoData = (this.repoReleases.assets || []).find(({name}) => $A.strExists(name, hostName)); if (this.repoData) { - let latestVersion = $A.leftDelete(this.releases.tag_name.toLowerCase(), "v") + let latestVersion = $A.leftDelete(this.repoReleases.tag_name.toLowerCase(), "v") console.log("Exist client: " + latestVersion); - this.status = 1; + this.repoStatus = 1; } } }, releasesNotification() { - if (this.downInfo.state != "completed") { - return; - } $A.modalConfirm({ okText: this.$L('立即更新'), onOk: () => { this.installApplication(); }, onCancel: () => { - this.status = 2; + this.repoStatus = 2; }, render: (h) => { return h('div', { @@ -209,12 +208,12 @@ export default { props: { color: 'volcano' } - }, this.releases.tag_name) + }, this.repoReleases.tag_name) ]), h('MarkdownPreview', { class: 'notification-body', props: { - initialValue: this.releases.body + initialValue: this.repoReleases.body } }), ]) @@ -227,7 +226,7 @@ export default { return; } this.$Electron.ipcRenderer.send('openFile', { - path: this.downInfo.savePath + path: this.downloadResult.savePath }); this.$Electron.ipcRenderer.send('windowQuit'); } diff --git a/resources/assets/sass/components/app-down.scss b/resources/assets/sass/components/app-down.scss index 81e12c1f..0e64f58b 100644 --- a/resources/assets/sass/components/app-down.scss +++ b/resources/assets/sass/components/app-down.scss @@ -28,7 +28,8 @@ } .notification-body { max-height: 210px; - overflow: auto; + overflow-x: hidden; + overflow-y: auto; margin: 18px 0; .markdown-preview { margin: -20px -12px;