From 2edbbcb871691f8798226d0522f9ee33f7595062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=98=89=E4=BC=9F?= <8473136@qq.com> Date: Sun, 23 Feb 2025 02:11:17 +0800 Subject: [PATCH] :bug: fix version handling and improve IPC communication for downloads --- electron/controller/ServerController.ts | 4 +- electron/controller/VersionController.ts | 44 +++++- electron/core/BeanFactory.ts | 26 ++++ electron/core/GlobalConstant.ts | 19 ++- electron/core/IpcRouter.ts | 14 +- electron/dao/BaseDao.ts | 35 +++-- electron/dao/VersionDao.ts | 2 +- electron/service/FileService.ts | 52 +++---- electron/service/FrpProcessService.ts | 74 ++++++++++ electron/service/ServerService.ts | 24 +--- electron/service/VersionService.ts | 131 +++++++++-------- electron/utils/IdUtils.ts | 48 ++----- electron/utils/PathUtils.ts | 4 + electron/utils/response.ts | 11 +- src/utils/ipcUtils.ts | 4 +- src/views/config/index.vue | 27 +++- src/views/download/index.vue | 171 ++++++++++++----------- types/core.d.ts | 2 +- types/frpc-desktop.d.ts | 6 +- 19 files changed, 447 insertions(+), 251 deletions(-) create mode 100644 electron/core/BeanFactory.ts create mode 100644 electron/service/FrpProcessService.ts diff --git a/electron/controller/ServerController.ts b/electron/controller/ServerController.ts index ac3b206..eeafb3f 100644 --- a/electron/controller/ServerController.ts +++ b/electron/controller/ServerController.ts @@ -11,7 +11,9 @@ class ServerController extends BaseController { } saveConfig(req: ControllerParam) { - console.log("save", req.args); + this._serverService.saveServerConfig(req.args).then(() => { + req.event.reply(req.channel, success()); + }) } getServerConfig(req: ControllerParam) { diff --git a/electron/controller/VersionController.ts b/electron/controller/VersionController.ts index 579f05f..fef09a7 100644 --- a/electron/controller/VersionController.ts +++ b/electron/controller/VersionController.ts @@ -1,13 +1,16 @@ import BaseController from "./BaseController"; import VersionService from "../service/VersionService"; -import { success } from "../utils/response"; +import { fail, success } from "../utils/response"; +import VersionDao from "../dao/VersionDao"; class VersionController extends BaseController { private readonly _versionService: VersionService; + private readonly _versionDao: VersionDao; - constructor(versionService: VersionService) { + constructor(versionService: VersionService, versionDao: VersionDao) { super(); this._versionService = versionService; + this._versionDao = versionDao; } getVersions(req: ControllerParam) { @@ -22,6 +25,43 @@ class VersionController extends BaseController { }); }); } + + getDownloadedVersions(req: ControllerParam) { + this._versionDao.findAll().then(data => { + req.event.reply(req.channel, success(data)); + }); + } + + downloadFrpVersion(req: ControllerParam) { + this._versionService + .downloadFrpVersion(req.args.githubReleaseId, progress => { + req.event.reply( + req.channel, + success({ + percent: progress.percent, + githubReleaseId: req.args.githubReleaseId, + completed: progress.percent >= 1 + }) + ); + }) + .then(r => { + console.log(2); + }) + .catch(err => { + console.log(1); + }); + } + + deleteDownloadedVersion(req: ControllerParam) { + this._versionService + .deleteFrpVersion(req.args.githubReleaseId) + .then(() => { + req.event.reply(req.channel, success()); + }) + .catch(err => { + req.event.reply(req.channel, fail()); + }); + } } export default VersionController; diff --git a/electron/core/BeanFactory.ts b/electron/core/BeanFactory.ts new file mode 100644 index 0000000..f5fbb1c --- /dev/null +++ b/electron/core/BeanFactory.ts @@ -0,0 +1,26 @@ +/** + * todo DI + */ +class BeanFactory { + private static _beans: Map = new Map(); + + private static registerBean(name: string, instance: any): void { + if (!this._beans.has(name)) { + this._beans.set(name, instance); + } + } + + public static getBean(name: string): T { + return this._beans.get(name); + } + + public static hasBean(name: string): boolean { + return this._beans.has(name); + } + + public static clear(): void { + this._beans.clear(); + } +} + +export default BeanFactory; diff --git a/electron/core/GlobalConstant.ts b/electron/core/GlobalConstant.ts index ab255f4..fa08158 100644 --- a/electron/core/GlobalConstant.ts +++ b/electron/core/GlobalConstant.ts @@ -1,13 +1,22 @@ -import path from "path"; -import { app } from "electron"; -import SecureUtils from "../utils/SecureUtils"; class GlobalConstant { - public static FRPC_STORAGE_FOLDER = ""; - + public static APP_NAME = "Frpc Desktop"; public static ZIP_EXT = ".zip"; public static GZ_EXT = ".gz"; public static TAR_GZ_EXT = ".tar.gz"; + + public static FRP_ARCH_VERSION_MAPPING = { + win32_x64: ["window", "amd64"], + win32_arm64: ["window", "arm64"], + win32_ia32: ["window", "386"], + darwin_arm64: ["darwin", "arm64"], + darwin_x64: ["darwin", "amd64"], + darwin_amd64: ["darwin", "amd64"], + linux_x64: ["linux", "amd64"], + linux_arm64: ["linux", "arm64"] + }; + + public static FRPC_PROCESS_STATUS_CHECK_INTERVAL = 3000; // public static APP_DATA_PATH = app.getPath("userData"); // public static DOWNLOAD_STORAGE_PATH = path.join( diff --git a/electron/core/IpcRouter.ts b/electron/core/IpcRouter.ts index 8cb400e..130d9d9 100644 --- a/electron/core/IpcRouter.ts +++ b/electron/core/IpcRouter.ts @@ -35,6 +35,18 @@ export const ipcRouters: IpcRouters = { getVersions: { path: "version/getVersions", controller: "versionController.getVersions" + }, + downloadVersion: { + path: "version/downloadVersion", + controller: "versionController.downloadFrpVersion" + }, + getDownloadedVersions: { + path: "version/getDownloadedVersions", + controller: "versionController.getDownloadedVersions" + }, + deleteDownloadedVersion: { + path: "version/deleteDownloadedVersion", + controller: "versionController.deleteDownloadedVersion" } } }; @@ -68,7 +80,7 @@ class IpcRouterConfigurate { ); const logService = new LogService(fileService); const serverController = new ServerController(serverService); - const versionController = new VersionController(versionService); + const versionController = new VersionController(versionService, versionDao); const logController = new LogController(logService); this._beans.set("serverDao", serverDao); diff --git a/electron/dao/BaseDao.ts b/electron/dao/BaseDao.ts index 5c60354..31d58a2 100644 --- a/electron/dao/BaseDao.ts +++ b/electron/dao/BaseDao.ts @@ -1,8 +1,7 @@ import Datastore from "nedb"; import path from "path"; -import Snowflakify from "snowflakify"; -import GlobalConstant from "../core/GlobalConstant"; import PathUtils from "../utils/PathUtils"; +import IdUtils from "../utils/IdUtils"; // interface BaseDaoInterface { // db: Datastore; @@ -25,10 +24,7 @@ class BaseDao { protected readonly db: Datastore; constructor(dbName: string) { - const dbFilename = path.join( - PathUtils.getAppData(), - `${dbName}-v2.db` - ); + const dbFilename = path.join(PathUtils.getAppData(), `${dbName}-v2.db`); this.db = new Datastore({ autoload: true, filename: dbFilename @@ -83,10 +79,17 @@ class BaseDao { }); } - // - // deleteById(id: string): void { - // return null; - // } + deleteById(id: string): Promise { + return new Promise((resolve, reject) => { + this.db.remove({ _id: id }, err => { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); + } // // findAll(): T[] { // return null; @@ -103,6 +106,18 @@ class BaseDao { }); }); } + + findAll(): Promise> { + return new Promise>((resolve, reject) => { + this.db.find({}, (err, document) => { + if (err) { + reject(err); + } else { + resolve(document); + } + }); + }); + } } export default BaseDao; diff --git a/electron/dao/VersionDao.ts b/electron/dao/VersionDao.ts index a26bf6d..4b58c22 100644 --- a/electron/dao/VersionDao.ts +++ b/electron/dao/VersionDao.ts @@ -18,7 +18,7 @@ class VersionDao extends BaseDao { } exists(githubReleaseId: number): Promise { - return new Promise((resolve, reject) => { + return new Promise(( resolve, reject) => { this.db.count({ githubReleaseId: githubReleaseId }, (err, count) => { if (err) { reject(err); diff --git a/electron/service/FileService.ts b/electron/service/FileService.ts index 697101c..e92a95f 100644 --- a/electron/service/FileService.ts +++ b/electron/service/FileService.ts @@ -4,8 +4,9 @@ import fs from "fs"; import zlib from "zlib"; import admZip from "adm-zip"; import GlobalConstant from "../core/GlobalConstant"; -import { logError, logInfo, LogModule } from "../utils/log"; + // import tar from "tar"; +const tar = require("tar"); class FileService { constructor() {} @@ -49,37 +50,40 @@ class FileService { // const frpcPath = path.join("frp", path.basename(zipFilePath, zipExt)); } - decompressTarGzFile(tarGzPath: string, targetPath: string) { + decompressTarGzFile(tarGzPath: string, targetPath: string, finish: Function) { // const targetFolder = path.join(targetPath, targetPath); const unzip = zlib.createGunzip(); const readStream = fs.createReadStream(tarGzPath); - // if (!fs.existsSync(unzip)) { - // fs.mkdirSync(targetPath, { recursive: true, mode: 0o777 }); - // } + if (!fs.existsSync(targetPath)) { + fs.mkdirSync(targetPath, { recursive: true, mode: 0o777 }); + } + readStream .pipe(unzip) .on("error", err => { - logError(LogModule.APP, `Error during gunzip: ${err.message}`); + // logError(LogModule.APP, `Error during gunzip: ${err.message}`); }) - // .pipe( - // tar - // .extract({ - // cwd: targetPath, - // filter: filePath => path.basename(filePath) === "frpc" - // }) - // .on("error", err => { - // logError( - // LogModule.APP, - // `Error extracting tar file: ${err.message}` - // ); - // }) - // ) + .pipe( + tar + .extract({ + cwd: targetPath, + strip: 1, + filter: filePath => path.basename(filePath) === "frpc" + }) + .on("error", err => { + // logError( + // LogModule.APP, + // `Error extracting tar file: ${err.message}` + // ); + }) + ) .on("finish", () => { - const frpcPath = path.join("frp", path.basename(tarGzPath, ".tar.gz")); - logInfo( - LogModule.APP, - `Extraction completed. Extracted directory: ${frpcPath}` - ); + finish(); + // const frpcPath = path.join("frp", path.basename(tarGzPath, ".tar.gz")); + // logInfo( + // LogModule.APP, + // `Extraction completed. Extracted directory: ${frpcPath}` + // ); }); } } diff --git a/electron/service/FrpProcessService.ts b/electron/service/FrpProcessService.ts new file mode 100644 index 0000000..8fb0bc3 --- /dev/null +++ b/electron/service/FrpProcessService.ts @@ -0,0 +1,74 @@ +import ServerService from "./ServerService"; +import VersionDao from "../dao/VersionDao"; +import PathUtils from "../utils/PathUtils"; +import { frpcProcess } from "../api/frpc"; +import GlobalConstant from "../core/GlobalConstant"; +import { Notification } from "electron"; + +const { exec, spawn } = require("child_process"); + +class FrpProcessService { + private readonly _serverService: ServerService; + private readonly _versionDao: VersionDao; + private _frpcProcess: any; + private _FrpcProcessListener: any; + + constructor(serverService: ServerService, versionDao: VersionDao) { + this._serverService = serverService; + this._versionDao = versionDao; + } + + isRunning(): boolean { + return false; + } + + async startFrpcProcess() { + const config = await this._serverService.getServerConfig(); + const version = await this._versionDao.findByGithubReleaseId( + config.frpcVersion + ); + // todo genConfigfile. + const configPath = ""; + const command = `${PathUtils.getFrpcFilename()} -c ${configPath}`; + this._frpcProcess = spawn(command, { + cwd: version.localPath, + shell: true + }); + + frpcProcess.stdout.on("data", data => { + // logDebug(LogModule.FRP_CLIENT, `Frpc process output: ${data}`); + }); + + frpcProcess.stdout.on("error", data => { + // logError(LogModule.FRP_CLIENT, `Frpc process error: ${data}`); + // stopFrpcProcess(() => {}); + this.stopFrpcProcess(); + }); + } + + stopFrpcProcess() {} + + watchFrpcProcess(listenerParam: ListenerParam) { + this._FrpcProcessListener = setInterval(() => { + const running = this.isRunning(); + // todo return status to view. + // logDebug( + // LogModule.FRP_CLIENT, + // `Monitoring frpc process status: ${status}, Listener ID: ${frpcStatusListener}` + // ); + if (!running) { + new Notification({ + title: GlobalConstant.APP_NAME, + body: "Connection lost, please check the logs for details." + }).show(); + // logError( + // LogModule.FRP_CLIENT, + // "Frpc process status check failed. Connection lost." + // ); + clearInterval(this._FrpcProcessListener); + } + }, GlobalConstant.FRPC_PROCESS_STATUS_CHECK_INTERVAL); + } +} + +export default FrpProcessService; diff --git a/electron/service/ServerService.ts b/electron/service/ServerService.ts index fe2496a..698a1dc 100644 --- a/electron/service/ServerService.ts +++ b/electron/service/ServerService.ts @@ -8,26 +8,14 @@ class ServerService extends BaseService { this._serverDao = serverDao; } - saveServerConfig(frpcServer: FrpcDesktopServer): Promise { - return new Promise((resolve, reject) => { - this._serverDao - .updateById("1", frpcServer) - .then(() => { - resolve(); - }) - .catch(err => reject(err)); - }); + async saveServerConfig( + frpcServer: FrpcDesktopServer + ): Promise { + return await this._serverDao.updateById("1", frpcServer); } - getServerConfig(): Promise { - return new Promise((resolve, reject) => { - this._serverDao - .findById("1") - .then((frpcServer: FrpcDesktopServer) => { - resolve(frpcServer); - }) - .catch(err => reject(err)); - }); + async getServerConfig(): Promise { + return await this._serverDao.findById("1"); } hasServerConfig(): Promise { diff --git a/electron/service/VersionService.ts b/electron/service/VersionService.ts index 2bcd470..49b6484 100644 --- a/electron/service/VersionService.ts +++ b/electron/service/VersionService.ts @@ -8,23 +8,9 @@ import { BrowserWindow } from "electron"; import GlobalConstant from "../core/GlobalConstant"; import path from "path"; import fs from "fs"; -import FileUtils from "../utils/FileUtils"; import SecureUtils from "../utils/SecureUtils"; import PathUtils from "../utils/PathUtils"; - -/** - * arch mapping - */ -const versionMapping = { - win32_x64: ["window", "amd64"], - win32_arm64: ["window", "arm64"], - win32_ia32: ["window", "386"], - darwin_arm64: ["darwin", "arm64"], - darwin_x64: ["darwin", "amd64"], - darwin_amd64: ["darwin", "amd64"], - linux_x64: ["linux", "amd64"], - linux_arm64: ["linux", "arm64"] -}; +import FileUtils from "../utils/FileUtils"; class VersionService extends BaseService { private readonly _versionDao: VersionDao; @@ -43,7 +29,7 @@ class VersionService extends BaseService { this._gitHubService = gitHubService; this._fileService = fileService; const nodeVersion = `${process.platform}_${process.arch}`; - this._currFrpArch = versionMapping[nodeVersion]; + this._currFrpArch = GlobalConstant.FRP_ARCH_VERSION_MAPPING[nodeVersion]; } downloadFrpVersion(githubReleaseId: number, onProgress: Function) { @@ -65,6 +51,9 @@ class VersionService extends BaseService { SecureUtils.calculateMD5(version.name) ); + if (fs.existsSync(versionFilePath)) { + fs.rmSync(versionFilePath, { recursive: true, force: true }); + } // const targetPath = path.resolve(); download(BrowserWindow.getFocusedWindow(), url, { filename: `${version.assetName}`, @@ -73,42 +62,78 @@ class VersionService extends BaseService { onProgress(progress); }, onCompleted: () => { - if (fs.existsSync(versionFilePath)) { - fs.rmSync(versionFilePath, { recursive: true, force: true }); - } const ext = path.extname(version.assetName); if (ext === GlobalConstant.ZIP_EXT) { this._fileService.decompressZipFile( downloadedFilePath, versionFilePath ); + // todo delete frps and other file. } else if ( ext === GlobalConstant.GZ_EXT && version.assetName.includes(GlobalConstant.TAR_GZ_EXT) ) { this._fileService.decompressTarGzFile( downloadedFilePath, - versionFilePath + versionFilePath, + () => { + // rename frpc. + const frpcFilePath = path.join(versionFilePath, "frpc"); + if (fs.existsSync(frpcFilePath)) { + const newFrpcFilePath = path.join( + versionFilePath, + PathUtils.getFrpcFilename() + ); + fs.renameSync(frpcFilePath, newFrpcFilePath); + } + // delete downloaded file. + // todo has bug. + const downloadedFile = path.join( + PathUtils.getDownloadStoragePath(), + version.assetName + ); + if (fs.existsSync(downloadedFile)) { + fs.rmSync(downloadedFile, { recursive: true, force: true }); + } + } ); } + + // todo 2025-02-23 delete downloaded file. version.localPath = versionFilePath; - this._versionDao.insert(version).then(data => { - resolve(data); - }); + version.downloaded = true; + this._versionDao + .insert(version) + .then(data => { + resolve(data); + }) + .catch(err => reject(err)); } }); }); } - deleteFrpVersion() {} + async deleteFrpVersion(githubReleaseId: number) { + if (!githubReleaseId) { + return; + } + const version = await this._versionDao.findByGithubReleaseId( + githubReleaseId + ); + if (this.frpcVersionExists(version)) { + fs.rmSync(version.localPath, { recursive: true, force: true }); + await this._versionDao.deleteById(version._id); + } + } - getFrpVersionsByGitHub(): Promise> { + async getFrpVersionsByGitHub(): Promise> { return new Promise>((resolve, reject) => { this._gitHubService .getGithubRepoAllReleases("fatedier/frp") - .then((releases: Array) => { + .then(async (releases: Array) => { const versions: Array = - this.githubRelease2FrpcVersion(releases); + await this.githubRelease2FrpcVersion(releases); + // const versions: Array = (this.versions = versions); this.versions = versions; resolve(versions); }) @@ -116,11 +141,8 @@ class VersionService extends BaseService { }); } - getFrpVersionByLocalJson(): Promise> { - return new Promise>(resolve => { - const versions = this.githubRelease2FrpcVersion(frpReleasesJson); - resolve(versions); - }); + async getFrpVersionByLocalJson(): Promise> { + return this.githubRelease2FrpcVersion(frpReleasesJson); } getFrpVersion() {} @@ -131,34 +153,24 @@ class VersionService extends BaseService { }); } - private githubRelease2FrpcVersion( + private async githubRelease2FrpcVersion( releases: Array - ): Array { + ): Promise> { + const allVersions = await this._versionDao.findAll(); return releases .filter(release => { return this.findCurrentArchitectureAsset(release.assets); }) .map(m => { const asset = this.findCurrentArchitectureAsset(m.assets); - // m.assets.forEach((ma: GithubAsset) => { - // // if (asset) { - // // const absPath = path.join( - // // frpPath, - // // asset.name.replace(/(\.tar\.gz|\.zip)$/, "") - // // ); - // // m.absPath = absPath; - // // m.download_completed = fs.existsSync(absPath); - // m.download_count = download_count; - // m.size = formatBytes(ma.size); - // // } - // }); - // const asset = getAdaptiveAsset(m.id); const download_count = m.assets.reduce( (sum, item) => sum + item.download_count, 0 ); + const currVersion = allVersions.find(ff => ff.githubReleaseId === m.id); const v: FrpcVersion = { + _id: "", githubReleaseId: m.id, githubAssetId: asset.id, githubCreatedAt: asset.created_at, @@ -167,25 +179,24 @@ class VersionService extends BaseService { versionDownloadCount: download_count, assetDownloadCount: asset.download_count, browserDownloadUrl: asset.browser_download_url, - downloaded: false, - localPath: "", + downloaded: this.frpcVersionExists(currVersion), + localPath: currVersion && currVersion.localPath, size: FileUtils.formatBytes(asset.size) }; - return v; }); } - // private async frpcVersionExists(githubReleaseId: number): boolean { - // const version = await this._versionDao.findByGithubReleaseId( - // githubReleaseId - // ); - // - // if (version) { - // return fs.existsSync(version.localPath); - // } - // return false; - // } + private frpcVersionExists(version: FrpcVersion): boolean { + // const version = await this._versionDao.findByGithubReleaseId( + // githubReleaseId + // ); + + if (version) { + return fs.existsSync(version.localPath); + } + return false; + } } export default VersionService; diff --git a/electron/utils/IdUtils.ts b/electron/utils/IdUtils.ts index 87e6fe2..f0df5f6 100644 --- a/electron/utils/IdUtils.ts +++ b/electron/utils/IdUtils.ts @@ -1,39 +1,21 @@ class IdUtils { public static genUUID() { - if (typeof crypto === "object") { - if (typeof crypto.randomUUID === "function") { - return crypto.randomUUID(); - } - if ( - typeof crypto.getRandomValues === "function" && - typeof Uint8Array === "function" - ) { - const callback = c => { - const num = Number(c); - return ( - num ^ - (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4))) - ).toString(16); - }; - return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, callback); + let uuidValue = "", + k, + randomValue; + for (k = 0; k < 32; k++) { + randomValue = (Math.random() * 16) | 0; + + if (k == 8 || k == 12 || k == 16 || k == 20) { + uuidValue += "-"; } + uuidValue += ( + k == 12 ? 4 : k == 16 ? (randomValue & 3) | 8 : randomValue + ).toString(16); } - let timestamp = new Date().getTime(); - let perforNow = - (typeof performance !== "undefined" && - performance.now && - performance.now() * 1000) || - 0; - return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, c => { - let random = Math.random() * 16; - if (timestamp > 0) { - random = (timestamp + random) % 16 | 0; - timestamp = Math.floor(timestamp / 16); - } else { - random = (perforNow + random) % 16 | 0; - perforNow = Math.floor(perforNow / 16); - } - return (c === "x" ? random : (random & 0x3) | 0x8).toString(16); - }); + return uuidValue; + } } + +export default IdUtils; diff --git a/electron/utils/PathUtils.ts b/electron/utils/PathUtils.ts index 6640815..141d911 100644 --- a/electron/utils/PathUtils.ts +++ b/electron/utils/PathUtils.ts @@ -18,6 +18,10 @@ class PathUtils { ); } + public static getFrpcFilename() { + return SecureUtils.calculateMD5("frpc") + } + public static getAppData() { return app.getPath("userData"); } diff --git a/electron/utils/response.ts b/electron/utils/response.ts index 3165da5..c099b9f 100644 --- a/electron/utils/response.ts +++ b/electron/utils/response.ts @@ -1,4 +1,4 @@ -export function success(data: any, message?: string) { +export function success(data?: any, message?: string) { const resp: ApiResponse = { success: true, data: data, @@ -7,6 +7,15 @@ export function success(data: any, message?: string) { return resp; } +// export function success(message?: string) { +// const resp: ApiResponse = { +// success: true, +// data: null, +// message: message || "successful." +// }; +// return resp; +// } + export function fail(message?: string) { const resp: ApiResponse = { success: false, diff --git a/src/utils/ipcUtils.ts b/src/utils/ipcUtils.ts index 52d36c9..abfc240 100644 --- a/src/utils/ipcUtils.ts +++ b/src/utils/ipcUtils.ts @@ -1,8 +1,8 @@ import { ipcRenderer } from "electron"; -export const send = (router: IpcRouter) => { +export const send = (router: IpcRouter, params?: any) => { console.log(router, "send.router"); - ipcRenderer.send(router.path); + ipcRenderer.send(router.path, params); }; export const on = (router: IpcRouter, listerHandler: (data: any) => void) => { diff --git a/src/views/config/index.vue b/src/views/config/index.vue index 0539dc9..062c089 100644 --- a/src/views/config/index.vue +++ b/src/views/config/index.vue @@ -179,7 +179,7 @@ const rules = reactive({ ] }); -const versions = ref>([]); +const versions = ref>([]); const copyServerConfigBase64 = ref(); const pasteServerConfigBase64 = ref(); @@ -234,13 +234,28 @@ const checkAndResetVersion = () => { } }; -onMounted(() => { +const handleLoadDownloadedVersion = () => { + send(ipcRouters.VERSION.getDownloadedVersions); +}; + +const handleLoadSavedConfig = () => { send(ipcRouters.SERVER.getServerConfig); +}; + +onMounted(() => { + handleLoadDownloadedVersion(); + handleLoadSavedConfig(); on(ipcRouters.SERVER.getServerConfig, data => { console.log("data", data); loading.value--; }); + + on(ipcRouters.VERSION.getDownloadedVersions, data => { + console.log("versions", data); + versions.value = data; + // checkAndResetVersion(); + }); // ipcRenderer.send("config.getConfig"); // handleLoadVersions(); // ipcRenderer.on("Config.getConfig.hook", (event, args) => { @@ -541,13 +556,13 @@ onUnmounted(() => { > + :value="v.githubReleaseId" + />
- + 手动刷新 diff --git a/src/views/download/index.vue b/src/views/download/index.vue index 0301ae9..da04374 100644 --- a/src/views/download/index.vue +++ b/src/views/download/index.vue @@ -7,13 +7,13 @@ import { ElMessage, ElMessageBox } from "element-plus"; import { useDebounceFn } from "@vueuse/core"; import IconifyIconOffline from "@/components/IconifyIcon/src/iconifyIconOffline"; import { on, send } from "@/utils/ipcUtils"; -import ipcRouter, { ipcRouters } from "../../../electron/core/IpcRouter"; +import { ipcRouters } from "../../../electron/core/IpcRouter"; defineComponent({ name: "Download" }); -const versions = ref>([]); +const versions = ref>([]); const loading = ref(1); const downloadPercentage = ref(0); const downloading = ref>(new Map()); @@ -28,28 +28,25 @@ const mirrors = ref>([ /** * 获取版本 */ -const handleLoadVersions = () => { - ipcRenderer.send("github.getFrpVersions", currMirror.value); +const handleLoadAllVersions = () => { + send(ipcRouters.VERSION.getVersions); }; /** * 下载 * @param version */ -const handleDownload = useDebounceFn((version: FrpVersion) => { - // console.log(version, currMirror.value); - ipcRenderer.send("github.download", { - versionId: version.id, - mirror: currMirror.value +const handleDownload = useDebounceFn((version: FrpcVersion) => { + send(ipcRouters.VERSION.downloadVersion, { + githubReleaseId: version.githubReleaseId }); - downloading.value.set(version.id, 0); }, 300); /** * 删除下载 * @param version */ -const handleDeleteVersion = useDebounceFn((version: FrpVersion) => { +const handleDeleteVersion = useDebounceFn((version: FrpcVersion) => { ElMessageBox.alert( `确认要删除 ${version.name} 吗?`, "提示", @@ -60,85 +57,86 @@ const handleDeleteVersion = useDebounceFn((version: FrpVersion) => { confirmButtonText: "删除" } ).then(() => { - ipcRenderer.send("github.deleteVersion", { - id: version.id, - absPath: version.absPath + send(ipcRouters.VERSION.deleteDownloadedVersion, { + githubReleaseId: version.githubReleaseId }); + // ipcRenderer.send("github.deleteVersion", { + // id: version.id, + // absPath: version.absPath + // }); }); }, 300); -const handleInitDownloadHook = () => { - ipcRenderer.on("Download.frpVersionHook", (event, args) => { - loading.value--; - versions.value = args.map(m => { - m.published_at = moment(m.published_at).format("YYYY-MM-DD"); - return m as FrpVersion; - }) as Array; - console.log(versions, "versions"); - }); - // 进度监听 - ipcRenderer.on("Download.frpVersionDownloadOnProgress", (event, args) => { - const { id, progress } = args; - downloading.value.set( - id, - Number(Number(progress.percent * 100).toFixed(2)) - ); - }); - ipcRenderer.on("Download.frpVersionDownloadOnCompleted", (event, args) => { - downloading.value.delete(args); - const version: FrpVersion | undefined = versions.value.find( - f => f.id === args - ); - if (version) { - version.download_completed = true; - } - }); - ipcRenderer.on("Download.deleteVersion.hook", (event, args) => { - const { err, data } = args; - if (!err) { - loading.value++; - ElMessage({ - type: "success", - message: "删除成功" - }); - handleLoadVersions(); - } - }); - ipcRenderer.on("Download.importFrpFile.hook", (event, args) => { - const { success, data } = args; - console.log(args); - - // if (err) { - loading.value++; - ElMessage({ - type: success ? "success" : "error", - message: data - }); - handleLoadVersions(); - // } - }); -}; +// const handleInitDownloadHook = () => { +// ipcRenderer.on("Download.deleteVersion.hook", (event, args) => { +// const { err, data } = args; +// if (!err) { +// loading.value++; +// ElMessage({ +// type: "success", +// message: "删除成功" +// }); +// handleLoadVersions(); +// } +// }); +// ipcRenderer.on("Download.importFrpFile.hook", (event, args) => { +// const { success, data } = args; +// console.log(args); +// +// // if (err) { +// loading.value++; +// ElMessage({ +// type: success ? "success" : "error", +// message: data +// }); +// handleLoadVersions(); +// // } +// }); +// }; const handleMirrorChange = () => { - handleLoadVersions(); + handleLoadAllVersions(); }; onMounted(() => { + handleLoadAllVersions(); - send(ipcRouters.VERSION.getVersions); - - on(ipcRouters.VERSION.getVersions, (data) => { - console.log('versionData', data); - // versions.value = args.map(m => { - // m.published_at = moment(m.published_at).format("YYYY-MM-DD"); - // return m as FrpVersion; - // }) as Array; + on(ipcRouters.VERSION.getVersions, data => { + console.log("versionData", data); + versions.value = data.map(m => { + m.githubCreatedAt = moment(m.githubCreatedAt).format("YYYY-MM-DD"); + return m as FrpcVersion; + }) as Array; + loading.value--; + }); + + on(ipcRouters.VERSION.downloadVersion, data => { + console.log("downloadData", data); + const { githubReleaseId, completed, percent } = data; + if (completed) { + downloading.value.delete(githubReleaseId); + const version: FrpcVersion | undefined = versions.value.find( + f => f.githubReleaseId === githubReleaseId + ); + if (version) { + version.downloaded = true; + } + } else { + downloading.value.set( + githubReleaseId, + Number(Number(percent * 100).toFixed(2)) + ); + } + }); + + on(ipcRouters.VERSION.deleteDownloadedVersion, () => { + loading.value++; + ElMessage({ + type: "success", + message: "删除成功" + }); + handleLoadAllVersions(); }); - // handleLoadVersions(); - // handleInitDownloadHook(); - // ipcRenderer.invoke("process").then((r: any) => { - // console.log(r, "rrr"); - // }); }); const handleImportFrp = () => { @@ -211,7 +209,7 @@ onUnmounted(() => { { {{ // moment(version.published_at).format("YYYY-MM-DD HH:mm:ss") - version.download_count + version.versionDownloadCount }}
发布时间:{{ // moment(version.published_at).format("YYYY-MM-DD HH:mm:ss") - version.published_at + version.githubCreatedAt }}
-
+
@@ -276,9 +274,12 @@ onUnmounted(() => {