diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml index ad9f39a331..6a662b6bb9 100644 --- a/.github/workflows/build-and-release.yml +++ b/.github/workflows/build-and-release.yml @@ -230,7 +230,6 @@ jobs: ren DevSidecar-${{ steps.package-info.outputs.version }}-x64.exe DevSidecar-${{ steps.package-info.outputs.version }}-windows-x86_64.exe; ren DevSidecar-${{ steps.package-info.outputs.version }}-ia32.exe DevSidecar-${{ steps.package-info.outputs.version }}-windows-ia32.exe; ren DevSidecar-${{ steps.package-info.outputs.version }}-arm64.exe DevSidecar-${{ steps.package-info.outputs.version }}-windows-arm64.exe; - ren DevSidecar-${{ steps.package-info.outputs.version }}.exe DevSidecar-${{ steps.package-info.outputs.version }}-windows-universal.exe; dir; - name: "Rename artifacts - Linux" if: ${{ matrix.os == 'ubuntu' }} @@ -292,13 +291,6 @@ jobs: path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-windows-arm64.exe name: "DevSidecar-${{ steps.package-info.outputs.version }}-windows-arm64.exe" if-no-files-found: error - - name: "Upload DevSidecar-${{ steps.package-info.outputs.version }}-windows-universal.exe" - uses: actions/upload-artifact@v4.4.0 - if: ${{ matrix.os == 'windows' }} - with: - path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-windows-universal.exe - name: "DevSidecar-${{ steps.package-info.outputs.version }}-windows-universal.exe" - if-no-files-found: error # endregion Upload artifacts - Windows # region Upload artifacts - Linux @@ -474,11 +466,6 @@ jobs: with: name: "DevSidecar-${{ steps.package-info.outputs.version }}-windows-arm64.exe" path: release - - name: "Download DevSidecar-${{ steps.package-info.outputs.version }}-windows-universal.exe" - uses: actions/download-artifact@v4.1.8 - with: - name: "DevSidecar-${{ steps.package-info.outputs.version }}-windows-universal.exe" - path: release # ------------------------------------------------------------------------------------------------------------------------- - name: "Download DevSidecar-${{ steps.package-info.outputs.version }}-linux-x86_64.deb" uses: actions/download-artifact@v4.1.8 @@ -575,4 +562,4 @@ jobs: GHR_PATH: release/ GHR_TITLE: ${{ github.ref_name }} GHR_REPLACE: true - GHR_DRAFT: true + GHR_DRAFT: true \ No newline at end of file diff --git a/.github/workflows/npm-run-electron.yml b/.github/workflows/npm-run-electron.yml index 6198d3a2f1..ee2b66848e 100644 --- a/.github/workflows/npm-run-electron.yml +++ b/.github/workflows/npm-run-electron.yml @@ -113,11 +113,9 @@ jobs: pnpm install; - name: "npm run electron" + working-directory: packages/gui run: | echo "======================================================================"; - echo "cd packages/gui"; - echo "--------------------"; - cd packages/gui; dir || ls -lah; echo "======================================================================"; diff --git a/.github/workflows/test-and-upload.yml b/.github/workflows/test-and-upload.yml index f042056bcf..830ed480d4 100644 --- a/.github/workflows/test-and-upload.yml +++ b/.github/workflows/test-and-upload.yml @@ -258,7 +258,6 @@ jobs: ren DevSidecar-${{ env.BUILD_VERSION }}-x64.exe DevSidecar-${{ env.BUILD_VERSION }}-windows-x86_64.exe; ren DevSidecar-${{ env.BUILD_VERSION }}-ia32.exe DevSidecar-${{ env.BUILD_VERSION }}-windows-ia32.exe; ren DevSidecar-${{ env.BUILD_VERSION }}-arm64.exe DevSidecar-${{ env.BUILD_VERSION }}-windows-arm64.exe; - ren DevSidecar-${{ env.BUILD_VERSION }}.exe DevSidecar-${{ env.BUILD_VERSION }}-windows-universal.exe; dir; - name: "Rename artifacts - Linux" if: ${{ matrix.os == 'ubuntu' }} @@ -320,13 +319,6 @@ jobs: path: packages/gui/dist_electron/DevSidecar-${{ env.BUILD_VERSION }}-windows-arm64.exe name: "DevSidecar-${{ env.BUILD_VERSION }}-windows-arm64.exe" if-no-files-found: error - - name: "Upload DevSidecar-${{ env.BUILD_VERSION }}-windows-universal.exe" - uses: actions/upload-artifact@v4.4.0 - if: ${{ matrix.os == 'windows' }} - with: - path: packages/gui/dist_electron/DevSidecar-${{ env.BUILD_VERSION }}-windows-universal.exe - name: "DevSidecar-${{ env.BUILD_VERSION }}-windows-universal.exe" - if-no-files-found: error # endregion Upload artifacts - Windows # region Upload artifacts - Linux @@ -465,4 +457,4 @@ jobs: path: packages/gui/dist_electron/DevSidecar-${{ env.BUILD_VERSION }}-macos-universal.dmg name: "DevSidecar-${{ env.BUILD_VERSION }}-macos-universal.dmg" if-no-files-found: error - # endregion Upload artifacts - macOS + # endregion Upload artifacts - macOS \ No newline at end of file diff --git a/package.json b/package.json index df0ebeb951..f9924d4f95 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ }, "devDependencies": { "@antfu/eslint-config": "^3.16.0", - "eslint": "^9.39.4", + "eslint": "^10.2.1", "eslint-plugin-format": "^0.1.3" }, "pnpm": { diff --git a/packages/core/src/modules/proxy/index.js b/packages/core/src/modules/proxy/index.js index 57e3f5325b..7fdd7810d2 100644 --- a/packages/core/src/modules/proxy/index.js +++ b/packages/core/src/modules/proxy/index.js @@ -17,7 +17,8 @@ const ProxyPlugin = function (context) { async setProxy () { const ip = '127.0.0.1' const port = config.get().server.port - const setEnv = config.get().proxy.setEnv + const proxyConfig = config.get().proxy || {} + const setEnv = proxyConfig.setEnv ?? false await shell.setSystemProxy({ ip, port, setEnv }) log.info(`开启系统代理成功:${ip}:${port}`) event.fire('status', { key: 'proxy.enabled', value: true }) @@ -26,7 +27,8 @@ const ProxyPlugin = function (context) { async unsetProxy (setEnv) { if (setEnv == null) { - setEnv = config.get().proxy.setEnv + const proxyConfig = config.get().proxy || {} + setEnv = proxyConfig.setEnv ?? false } try { await shell.setSystemProxy({ setEnv }) diff --git a/packages/gui/babel.config.js b/packages/gui/babel.config.cjs similarity index 100% rename from packages/gui/babel.config.js rename to packages/gui/babel.config.cjs diff --git a/packages/gui/electron-builder.config.cjs b/packages/gui/electron-builder.config.cjs new file mode 100644 index 0000000000..9a860b31e5 --- /dev/null +++ b/packages/gui/electron-builder.config.cjs @@ -0,0 +1,104 @@ +const publishUrl = process.env.VUE_APP_PUBLISH_URL +const publishProvider = process.env.VUE_APP_PUBLISH_PROVIDER + +/** @type {import('electron-builder').Configuration} */ +module.exports = { + appId: 'dev-sidecar', + productName: 'dev-sidecar', + artifactName: 'DevSidecar-${version}-${arch}.${ext}', + copyright: 'Copyright © 2020-' + new Date().getFullYear() + ' Greper, WangLiang, CuteOmega', + directories: { + output: 'dist_electron', + buildResources: 'build', + }, + files: [ + { + from: 'dist', + to: 'dist', + filter: [ + '**/*', + '!win-*/**/*', + '!mac-*/**/*', + '!linux-*/**/*', + '!*.zip', + '!*.dmg', + '!*.blockmap', + '!*.exe', + '!*.AppImage', + '!*.deb', + '!*.rpm', + '!*.tar.gz', + '!*.flatpak', + '!builder-*.yml', + '!builder-*.yaml', + ], + }, + 'src/**/*', + 'package.json', + 'extra/**/*', + ], + extraResources: [ + { + from: 'extra', + to: 'extra', + }, + ], + afterPack: './pkg/after-pack.cjs', + afterAllArtifactBuild: './pkg/after-all-artifact-build.cjs', + nsis: { + oneClick: false, + perMachine: true, + allowElevation: true, + allowToChangeInstallationDirectory: true, + }, + win: { + icon: 'build/icons/', + target: [ + { + target: 'nsis', + arch: ['x64', 'ia32', 'arm64'], + }, + ], + }, + linux: { + icon: 'build/mac/', + target: [ + { + target: 'deb', + arch: ['x64', 'arm64', 'armv7l'], + }, + { + target: 'AppImage', + arch: ['x64', 'arm64', 'armv7l'], + }, + { + target: 'tar.gz', + arch: ['x64', 'arm64', 'armv7l'], + }, + { + target: 'rpm', + arch: ['x64', 'arm64', 'armv7l'], + }, + { + target: 'flatpak', + arch: ['x64'], + }, + ], + appId: 'cn.docmirror.DevSidecar', + category: 'System', + }, + mac: { + icon: './build/mac/icon.icns', + target: { + target: 'dmg', + arch: ['x64', 'arm64', 'universal'], + }, + category: 'public.app-category.developer-tools', + }, + publish: publishProvider + ? { + provider: publishProvider, + url: publishUrl, + } + : undefined, +} diff --git a/packages/gui/package.json b/packages/gui/package.json index 7c712d7c5c..f43b57c40d 100644 --- a/packages/gui/package.json +++ b/packages/gui/package.json @@ -2,6 +2,8 @@ "name": "@docmirror/dev-sidecar-gui", "version": "2.1.0", "private": false, + "type": "module", + "main": "src/background.js", "author": { "email": "xiaojunnuo@qq.com", "name": "Greper" @@ -10,9 +12,10 @@ "homepage": "https://github.com/docmirror/dev-sidecar", "scripts": { "serve": "vue-cli-service serve", + "build": "vue-cli-service build", "lint": "vue-cli-service lint", - "electron:build": "vue-cli-service electron:build", - "electron": "vue-cli-service electron:serve", + "electron": "concurrently -k \"vue-cli-service serve --port 8080\" \"wait-on http-get://localhost:8080 && cross-env WEBPACK_DEV_SERVER_URL=http://localhost:8080 electron .\"", + "electron:build": "npm run build && electron-builder --config electron-builder.config.cjs", "postinstall": "electron-builder install-app-deps", "postuninstall": "electron-builder install-app-deps", "electron:icons": "electron-icon-builder --input=./public/logo/win.png --output=build --flatten", @@ -24,32 +27,39 @@ "@docmirror/mitmproxy": "workspace:*", "@starknt/shutdown-handler-napi": "^0.0.3", "@starknt/sysproxy": "^0.0.3", - "@vscode/sudo-prompt": "^9.3.1", - "adm-zip": "^0.5.16", - "ant-design-vue": "^1.7.8", + "@vscode/sudo-prompt": "^9.3.2", + "adm-zip": "^0.5.17", + "ant-design-vue": "^4.2.6", + "archiver": "^7.0.1", + "core-js": "^3.49.0", "electron-baidu-tongji": "^1.0.5", - "electron-updater": "^6.3.9", + "electron-updater": "^6.8.3", "json5": "^2.2.3", - "lodash": "^4.17.21", + "lodash": "^4.18.1", + "minimist": "^1.2.8", "request-progress": "^3.0.0", - "sass": "^1.81.0", - "sass-loader": "^16.0.3", - "search-bar-vue2": "^1.0.0", - "vue": "^2.7.16", - "vue-json-editor-fix-cn": "^1.4.3", - "vue-router": "^3.6.5" + "sass": "^1.99.0", + "sass-loader": "^16.0.7", + "tiny-emitter": "^2.1.0", + "vue": "^3.5.33", + "vue-router": "^4.6.4", + "vue3-json-editor": "^1.1.5" }, "devDependencies": { - "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/core": "^7.29.0", + "@babel/plugin-syntax-jsx": "^7.28.6", "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0", "@vue/babel-preset-jsx": "^1.4.0", - "@vue/cli-plugin-babel": "^5.0.8", - "@vue/cli-service": "^5.0.8", - "electron": "^19.1.9", - "electron-builder": "^25.1.8", + "@vue/cli-plugin-babel": "^5.0.9", + "@vue/cli-service": "^5.0.9", + "concurrently": "^8.2.2", + "cross-env": "^7.0.3", + "electron": "^41.3.0", + "electron-builder": "^26.8.1", "electron-icon-builder": "^2.0.1", "json5-loader": "^4.0.1", - "vue-cli-plugin-electron-builder": "^3.0.0-alpha.4" + "path-browserify": "^1.0.1", + "wait-on": "^7.2.0" }, "browserslist": [ "> 1%", diff --git a/packages/gui/pkg/after-all-artifact-build.js b/packages/gui/pkg/after-all-artifact-build.cjs similarity index 55% rename from packages/gui/pkg/after-all-artifact-build.js rename to packages/gui/pkg/after-all-artifact-build.cjs index 5ab94876f5..83e70675cd 100644 --- a/packages/gui/pkg/after-all-artifact-build.js +++ b/packages/gui/pkg/after-all-artifact-build.cjs @@ -6,15 +6,15 @@ function appendIntro (context, systemType, latest) { const version = pkg.version const partUpdateFile = `update-${systemType}-${version}.zip` - const partUpdateUrl = context.configuration.publish.url + partUpdateFile + const publishConfig = context.configuration.publish + if (!publishConfig || !publishConfig.url) { + console.log(`跳过 latest 修改: ${latest},publish 配置不可用`) + return + } + const partUpdateUrl = publishConfig.url + partUpdateFile const latestFilePath = path.join(context.outDir, latest) - fs.appendFile(latestFilePath, `partPackage: ${partUpdateUrl} -partMiniVersion: 1.7.0 -releaseNotes: - - 升级日志 - - https://download.fastgit.org/docmirror/dev-sidecar/releases/download/v${version}/DevSidecar-${version}.exe -`, (err) => { + fs.appendFile(latestFilePath, `partPackage: ${partUpdateUrl}\npartMiniVersion: 1.7.0\nreleaseNotes:\n - 升级日志\n - https://download.fastgit.org/docmirror/dev-sidecar/releases/download/v${version}/DevSidecar-${version}.exe\n`, (err) => { if (err) { console.log('修改latest 失败') } diff --git a/packages/gui/pkg/after-pack.js b/packages/gui/pkg/after-pack.cjs similarity index 59% rename from packages/gui/pkg/after-pack.js rename to packages/gui/pkg/after-pack.cjs index 6e3138ecd8..73a0c077e3 100644 --- a/packages/gui/pkg/after-pack.js +++ b/packages/gui/pkg/after-pack.cjs @@ -1,9 +1,9 @@ const fs = require('node:fs') const path = require('node:path') -const AdmZip = require('adm-zip') +const archiver = require('archiver') const pkg = require('../package.json') -function writeAppUpdateYmlForLinux () { +function writeAppUpdateYmlForLinux (appOutDir) { const publishUrl = process.env.VUE_APP_PUBLISH_URL const publishProvider = process.env.VUE_APP_PUBLISH_PROVIDER // provider: generic @@ -11,10 +11,10 @@ function writeAppUpdateYmlForLinux () { // updaterCacheDirName: '@docmirrordev-sidecar-gui-updater' const fileContent = `provider: ${publishProvider} url: '${publishUrl}' -updaterCacheDirName: '@docmirrordev-sidecar-gui-updater' +updaterCacheDirName: 'dev-sidecar-gui-updater' ` console.log('write linux app-update.yml,updateUrl:', publishUrl) - const filePath = path.resolve('./dist_electron/linux-unpacked/resources/app-update.yml') + const filePath = path.join(appOutDir, 'resources', 'app-update.yml') fs.writeFileSync(filePath, fileContent) } exports.default = async function (context) { @@ -26,13 +26,29 @@ exports.default = async function (context) { } else if (context.packager.platform.nodeName === 'linux') { targetPath = path.join(context.appOutDir, './resources') systemType = 'linux' - writeAppUpdateYmlForLinux() + writeAppUpdateYmlForLinux(context.appOutDir) } else { targetPath = path.join(context.appOutDir, './resources') systemType = 'win' } - const zip = new AdmZip() - zip.addLocalFolder(targetPath) const partUpdateFile = `update-${systemType}-${pkg.version}.zip` - zip.writeZip(path.join(context.outDir, partUpdateFile)) + const outputPath = path.join(context.outDir, partUpdateFile) + + await new Promise((resolve, reject) => { + const output = fs.createWriteStream(outputPath) + const archive = archiver('zip', { zlib: { level: 9 } }) + + output.on('close', () => { + console.log(`Created ${partUpdateFile}, size: ${(archive.pointer() / 1024 / 1024).toFixed(2)} MB`) + resolve() + }) + + archive.on('error', (err) => { + reject(err) + }) + + archive.pipe(output) + archive.directory(targetPath, false) + archive.finalize() + }) } diff --git a/packages/gui/src/background.js b/packages/gui/src/background.js index b7d5593847..5844616ced 100644 --- a/packages/gui/src/background.js +++ b/packages/gui/src/background.js @@ -1,13 +1,12 @@ 'use strict' -/* global __static */ import path from 'node:path' +import { fileURLToPath } from 'node:url' import DevSidecar from '@docmirror/dev-sidecar' -import { app, BrowserWindow, dialog, globalShortcut, ipcMain, Menu, nativeImage, nativeTheme, powerMonitor, protocol, Tray } from 'electron' +import { app, BrowserWindow, dialog, globalShortcut, ipcMain, Menu, nativeImage, nativeTheme, powerMonitor, Tray } from 'electron' import minimist from 'minimist' -import { createProtocol } from 'vue-cli-plugin-electron-builder/lib' -import backend from './bridge/backend' -import jsonApi from '@docmirror/mitmproxy/src/json' -import log from './utils/util.log.gui' +import backend from './bridge/backend.js' +import jsonApi from '@docmirror/mitmproxy/src/json.js' +import log from './utils/util.log.gui.js' log.info(`background.js start, platform is ${process.platform}`) @@ -15,17 +14,13 @@ const isWindows = process.platform === 'win32' const isLinux = process.platform === 'linux' const isMac = process.platform === 'darwin' +const __dirname = path.dirname(fileURLToPath(import.meta.url)) const isDevelopment = process.env.NODE_ENV !== 'production' +const staticPath = isDevelopment + ? path.resolve('public') + : path.join(app.getAppPath(), 'dist') -// 避免其他系统出现异常,只有 Windows 使用 './background/powerMonitor' let _powerMonitor = powerMonitor -if (isWindows) { - try { - _powerMonitor = require('./background/powerMonitor').powerMonitor - } catch (e) { - log.error(`加载 './background/powerMonitor' 失败,现捕获异常并使用默认的 powerMonitor。\r\n目前,启动着DS重启电脑时,将无法正常关闭系统代理,届时请自行关闭系统代理!\r\n捕获的异常信息:`, e) - } -} // Keep a global reference of the window object, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. @@ -42,10 +37,7 @@ try { } let hideDockWhenWinClose = DevSidecar.api.config.get().app.dock.hideWhenWinClose || false -// Scheme must be registered before the app is ready -protocol.registerSchemesAsPrivileged([ - { scheme: 'app', privileges: { secure: true, standard: true } }, -]) + function openDevTools () { try { @@ -222,7 +214,7 @@ function createWindow (startHideWindow, autoQuitIfError = true) { nodeIntegration: true, // process.env.ELECTRON_NODE_INTEGRATION }, show: !startHideWindow, - icon: path.join(__static, 'icon.png'), + icon: path.join(staticPath, 'icon.png'), }) } catch (e) { log.error('创建窗口失败:', e) @@ -249,9 +241,8 @@ function createWindow (startHideWindow, autoQuitIfError = true) { setTimeout(openDevTools, 2000) } } else { - createProtocol('app') // Load the index.html when not in development - win.loadURL('app://./index.html') + win.loadFile(path.join(app.getAppPath(), 'dist', 'index.html')) } if (startHideWindow) { @@ -494,14 +485,14 @@ try { // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.on('ready', async () => { - // if (isDevelopment && !process.env.IS_TEST) { - // // Install Vue Devtools - // try { - // await installExtension(VUEJS_DEVTOOLS) - // } catch (e) { - // log.error('Vue Devtools failed to install:', e.toString()) - // } - // } + if (isWindows) { + try { + const mod = await import('./background/powerMonitor.js') + _powerMonitor = mod.powerMonitor + } catch (e) { + log.error(`加载 './background/powerMonitor' 失败,现捕获异常并使用默认的 powerMonitor。\r\n目前,启动着DS重启电脑时,将无法正常关闭系统代理,届时请自行关闭系统代理!\r\n捕获的异常信息:`, e) + } + } try { if (!createWindow(startHideWindow)) { diff --git a/packages/gui/src/bridge/api/backend.js b/packages/gui/src/bridge/api/backend.js index 423370e9a6..2441882d90 100644 --- a/packages/gui/src/bridge/api/backend.js +++ b/packages/gui/src/bridge/api/backend.js @@ -1,19 +1,23 @@ import fs from 'node:fs' import path from 'node:path' +import { fileURLToPath } from 'node:url' import DevSidecar from '@docmirror/dev-sidecar' -import { ipcMain } from 'electron' +import { app, ipcMain } from 'electron' import lodash from 'lodash' - -const jsonApi = require('@docmirror/mitmproxy/src/json') +import jsonApi from '@docmirror/mitmproxy/src/json.js' +import { createRequire } from 'node:module' +const require = createRequire(import.meta.url) const pk = require('../../../package.json') -const coreDefaultConfig = require('@docmirror/dev-sidecar/src/config/index.js') -const configLoader = require('@docmirror/dev-sidecar/src/config/local-config-loader.js') -const configFromFiles = require('@docmirror/dev-sidecar/src/config/index.js').configFromFiles -const log = require('../../utils/util.log.gui') -const dateUtil = require('@docmirror/dev-sidecar/src/utils/util.date') +import coreDefaultConfig from '@docmirror/dev-sidecar/src/config/index.js' +import configLoader from '@docmirror/dev-sidecar/src/config/local-config-loader.js' +import log from '../../utils/util.log.gui.js' +import dateUtil from '@docmirror/dev-sidecar/src/utils/util.date.js' + +const { configFromFiles } = coreDefaultConfig -const mitmproxyPath = path.join(__dirname, 'mitmproxy.js') -process.env.DS_EXTRA_PATH = path.join(__dirname, '../extra/') +const __dirname = path.dirname(fileURLToPath(import.meta.url)) +const mitmproxyPath = path.join(__dirname, '../mitmproxy.js') +process.env.DS_EXTRA_PATH = path.join(app.getAppPath(), 'extra') let currentWin const getDefaultConfigBasePath = function () { diff --git a/packages/gui/src/bridge/api/open-enable-loopback.js b/packages/gui/src/bridge/api/open-enable-loopback.js index 7e2e910168..2ec3f9ace7 100644 --- a/packages/gui/src/bridge/api/open-enable-loopback.js +++ b/packages/gui/src/bridge/api/open-enable-loopback.js @@ -1,14 +1,17 @@ -/* global __static */ +import { app } from 'electron' import DevSidecar from '@docmirror/dev-sidecar' import sudoPrompt from '@vscode/sudo-prompt' import { join } from 'node:path' -import log from '../../utils/util.log.gui' +import log from '../../utils/util.log.gui.js' + +const isDevelopment = process.env.NODE_ENV !== 'production' +const extraPath = join(process.cwd(), 'extra') export default { open () { const options = { name: 'EnableLoopback', - icns: process.platform === 'darwin' ? join(__static, 'icon.icns') : undefined, + icns: process.platform === 'darwin' ? join(extraPath, 'icons/icon.icns') : undefined, env: { PARAM: 'VALUE' }, } const exeFile = DevSidecar.api.shell.extraPath.getEnableLoopbackPath() diff --git a/packages/gui/src/bridge/auto-start/front.js b/packages/gui/src/bridge/auto-start/front.js index 4d19525b1a..1e18cdb5d4 100644 --- a/packages/gui/src/bridge/auto-start/front.js +++ b/packages/gui/src/bridge/auto-start/front.js @@ -1,9 +1,9 @@ function install (app, api) { api.ipc.on('auto-start', (event, message) => { if (message.value === true) { - app.$message.info('已添加开机自启') + app.config.globalProperties.$message.info('已添加开机自启') } else { - app.$message.info('已取消开机自启') + app.config.globalProperties.$message.info('已取消开机自启') } }) api.autoStart = { diff --git a/packages/gui/src/bridge/backend.js b/packages/gui/src/bridge/backend.js index 0c1d111fe6..fc3583d3b6 100644 --- a/packages/gui/src/bridge/backend.js +++ b/packages/gui/src/bridge/backend.js @@ -1,9 +1,9 @@ -import api from './api/backend' -import autoStart from './auto-start/backend' -import fileSelector from './file-selector/backend' -import tongji from './tongji/backend' -import update from './update/backend' -import log from '../utils/util.log.gui' +import api from './api/backend.js' +import autoStart from './auto-start/backend.js' +import fileSelector from './file-selector/backend.js' +import tongji from './tongji/backend.js' +import update from './update/backend.js' +import log from '../utils/util.log.gui.js' const modules = { api, // 核心接口模块 diff --git a/packages/gui/src/bridge/error/front.js b/packages/gui/src/bridge/error/front.js index ef5d6e3353..68074e586c 100644 --- a/packages/gui/src/bridge/error/front.js +++ b/packages/gui/src/bridge/error/front.js @@ -22,14 +22,14 @@ function handleServerStartError (message, err, app, api) { } latestConfirmTime = now - app.$confirm({ + app.config.globalProperties.$confirm({ title: '端口被占用,代理服务启动失败', content: '是否要杀掉占用进程?您也可以点击取消,然后前往加速服务->基本设置中修改代理端口', onOk () { api.config.get().then((config) => { console.log('config:', config) api.shell.killByPort({ port: config.server.port }).then((ret) => { - app.$message.info('杀掉进程成功,请重试开启代理服务') + app.config.globalProperties.$message.info('杀掉进程成功,请重试开启代理服务') }) }) }, @@ -38,7 +38,7 @@ function handleServerStartError (message, err, app, api) { }, }) } else { - app.$message.error(`加速服务启动失败:${message.message}`) + app.config.globalProperties.$message.error(`加速服务启动失败:${message.message}`) } } diff --git a/packages/gui/src/bridge/mitmproxy.js b/packages/gui/src/bridge/mitmproxy.js index d51fc9096b..69a0635329 100644 --- a/packages/gui/src/bridge/mitmproxy.js +++ b/packages/gui/src/bridge/mitmproxy.js @@ -1,9 +1,11 @@ -const fs = require('node:fs') -const path = require('node:path') -const server = require('@docmirror/mitmproxy') -const jsonApi = require('@docmirror/mitmproxy/src/json') -const log = require('@docmirror/mitmproxy/src/utils/util.log.server') // 当前脚本是在 server 的进程中执行的,所以使用 mitmproxy 中的logger +import fs from 'node:fs' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import server from '@docmirror/mitmproxy' +import jsonApi from '@docmirror/mitmproxy/src/json.js' +import log from '@docmirror/mitmproxy/src/utils/util.log.server.js' // 当前脚本是在 server 的进程中执行的,所以使用 mitmproxy 中的logger +const __dirname = path.dirname(fileURLToPath(import.meta.url)) const configPath = process.argv[2] const configJson = fs.readFileSync(configPath) log.info('读取 running.json by gui bridge 成功:', configPath) diff --git a/packages/gui/src/bridge/on-close/front.js b/packages/gui/src/bridge/on-close/front.js index 53b50f8b53..d710d28924 100644 --- a/packages/gui/src/bridge/on-close/front.js +++ b/packages/gui/src/bridge/on-close/front.js @@ -1,36 +1,52 @@ +import { h, resolveComponent } from 'vue' + let closeType = 2 let doSave = false function install (app, api) { api.ipc.on('close.showTip', (event, message) => { console.info('ipc channel: "close.showTip", event:', event, ', message:', message) - function onRadioChange (event) { - closeType = event.target.value + function onRadioChange (e) { + closeType = parseInt(e.target.value) } - function onCheckChange (event) { - doSave = event.target.checked + function onCheckChange (e) { + doSave = e.target.checked } - app.$confirm({ + + const shortcut = message.showHideShortcut || '无' + + const ARadioGroup = resolveComponent('a-radio-group') + const ARadio = resolveComponent('a-radio') + const ACheckbox = resolveComponent('a-checkbox') + + // 使用 h 函数创建 VNode + const content = h('div', {}, [ + h('div', { style: { marginTop: '10px' } }, [ + h(ARadioGroup, { + value: closeType, + 'onUpdate:value': (val) => { closeType = val }, + onChange: onRadioChange, + }, [ + h(ARadio, { value: 1 }, '直接关闭'), + h(ARadio, { value: 2 }, '最小化到系统托盘'), + ]), + ]), + h('div', { style: { marginTop: '10px' } }, [ + h(ACheckbox, { + checked: doSave, + 'onUpdate:checked': (val) => { doSave = val }, + onChange: onCheckChange, + }, '记住本次选择,不再提示'), + ]), + h('div', { style: { marginTop: '20px' } }, [ + '提示:打开窗口的快捷键为 ', + h('code', {}, shortcut), + ]), + ]) + + app.config.globalProperties.$confirm({ title: '关闭策略', - content: (h) => ( -
-
- - 直接关闭 - 最小化到系统托盘 - -
-
- - 记住本次选择,不再提示 - -
-
- 提示:打开窗口的快捷键为 - {message.showHideShortcut || '无'} -
-
- ), + content, async onOk () { console.log('OK. closeType=', closeType, ', doSave:', doSave) if (doSave) { diff --git a/packages/gui/src/bridge/tongji/backend.js b/packages/gui/src/bridge/tongji/backend.js index 78d399f625..2ff705f116 100644 --- a/packages/gui/src/bridge/tongji/backend.js +++ b/packages/gui/src/bridge/tongji/backend.js @@ -2,9 +2,10 @@ * first step * @param {*} ipcMain */ +import request from 'request' + function ebtMain (ipcMain) { const isDevelopment = process.env.NODE_ENV !== 'production' - const request = require('request') /* istanbul ignore else */ if (!(ipcMain && ipcMain.on)) { throw new TypeError('require ipcMain') diff --git a/packages/gui/src/bridge/update/backend.js b/packages/gui/src/bridge/update/backend.js index 7619d7467f..cb39cb24fd 100644 --- a/packages/gui/src/bridge/update/backend.js +++ b/packages/gui/src/bridge/update/backend.js @@ -1,16 +1,21 @@ import fs from 'node:fs' import path from 'node:path' +import { fileURLToPath } from 'node:url' import DevSidecar from '@docmirror/dev-sidecar' import AdmZip from 'adm-zip' import { ipcMain } from 'electron' -import { autoUpdater } from 'electron-updater' +import electronUpdater from 'electron-updater' +const { autoUpdater } = electronUpdater import request from 'request' import progress from 'request-progress' -import pkg from '../../../package.json' -import appPathUtil from '../../utils/util.apppath' -import log from '../../utils/util.log.gui' -import { isNewVersion } from '@docmirror/dev-sidecar/src/utils/util.version' +import { createRequire } from 'node:module' +const require = createRequire(import.meta.url) +const pkg = require('../../../package.json') +import appPathUtil from '../../utils/util.apppath.js' +import log from '../../utils/util.log.gui.js' +import { isNewVersion } from '@docmirror/dev-sidecar/src/utils/util.version.js' +const __dirname = path.dirname(fileURLToPath(import.meta.url)) const isMac = process.platform === 'darwin' const isLinux = process.platform === 'linux' diff --git a/packages/gui/src/bridge/update/front.js b/packages/gui/src/bridge/update/front.js index 51a0436f1e..9e90fe62bd 100644 --- a/packages/gui/src/bridge/update/front.js +++ b/packages/gui/src/bridge/update/front.js @@ -1,5 +1,5 @@ function install (app, api) { - const updateParams = app.$global.update = { fromUser: false, autoDownload: false, progress: 0, checking: false, downloading: false, newVersion: false, isFullUpdate: true } + const updateParams = app.config.globalProperties.$global.update = { fromUser: false, autoDownload: false, progress: 0, checking: false, downloading: false, newVersion: false, isFullUpdate: true } api.ipc.on('update', (event, message) => { console.log('on message', event, message) handleUpdateMessage(message, app) @@ -52,7 +52,7 @@ function install (app, api) { return // 不是手动检查更新,不提示错误信息,避免打扰 } const error = message.error - app.$message.error((error == null ? '未知错误' : (error.stack || error).toString())) + app.config.globalProperties.$message.error((error == null ? '未知错误' : (error.stack || error).toString())) } } } @@ -60,7 +60,7 @@ function install (app, api) { function noNewVersion () { updateParams.newVersion = false if (updateParams.fromUser) { - app.$message.info('当前已经是最新版本') + app.config.globalProperties.$message.info('当前已经是最新版本') } } @@ -74,7 +74,7 @@ function install (app, api) { function goManualUpdate (value) { updateParams.newVersion = false - app.$confirm({ + app.config.globalProperties.$confirm({ title: '暂不提供自动升级', cancelText: '取消', okText: '打开链接', @@ -139,13 +139,13 @@ function install (app, api) { updateParams.newVersion = true if (updateParams.autoDownload !== false) { - app.$message.info('发现新版本,正在下载中...') + app.config.globalProperties.$message.info('发现新版本,正在下载中...') downloadNewVersion(value) return } console.log(value) - app.$confirm({ + app.config.globalProperties.$confirm({ title: `发现新版本:v${value.version}`, cancelText: '暂不升级', okText: '升级', @@ -197,7 +197,7 @@ function install (app, api) { function newUpdateIsReady (value) { updateParams.downloading = false console.log(value) - app.$confirm({ + app.config.globalProperties.$confirm({ title: `新版本(v${value.version})已准备好,是否立即升级?`, cancelText: '暂不升级', okText: '立即升级', diff --git a/packages/gui/src/main.js b/packages/gui/src/main.js index e89daaa062..0f067b140e 100644 --- a/packages/gui/src/main.js +++ b/packages/gui/src/main.js @@ -1,13 +1,12 @@ import antd from 'ant-design-vue' -import Vue from 'vue' -import VueRouter from 'vue-router' -import SearchBar from 'search-bar-vue2' +import { createApp } from 'vue'; +import { createRouter, createWebHashHistory } from 'vue-router'; import { ipcRenderer } from 'electron' import view from './view' import App from './view/App.vue' import DsContainer from './view/components/container' import routes from './view/router' -import 'ant-design-vue/dist/antd.css' +import 'ant-design-vue/dist/reset.css' import './view/style/index.scss' import './view/style/theme/dark.scss' // 暗色主题 @@ -23,25 +22,23 @@ try { console.info('main.js start') ipcRenderer.send('main.js start') - Vue.config.productionTip = false - Vue.use(antd) - Vue.use(VueRouter) - Vue.use(SearchBar) - Vue.component(DsContainer) // 3. 创建 router 实例,然后传 `routes` 配置 // 你还可以传别的配置参数, 不过先这么简单着吧。 - const router = new VueRouter({ + const router = createRouter({ + history: createWebHashHistory(), routes, // (缩写) 相当于 routes: routes }) - const app = new Vue({ - router, - render: h => h(App), - }) + const app = createApp(App) + + app.use(antd) + app.use(router) + app.component('DsContainer', DsContainer) + view.initApi(app).then(async (api) => { // 初始化status try { - await view.initPre(Vue, api) - app.$mount('#app') + await view.initPre(app, api) + app.mount('#app') view.initModules(app, router) } catch (e) { console.error('view初始化出现未知异常:', e) @@ -49,16 +46,6 @@ try { } }) - // fix vue-router NavigationDuplicated - const VueRouterPush = VueRouter.prototype.push - VueRouter.prototype.push = function push (location) { - return VueRouterPush.call(this, location).catch(err => err) - } - const VueRouterReplace = VueRouter.prototype.replace - VueRouter.prototype.replace = function replace (location) { - return VueRouterReplace.call(this, location).catch(err => err) - } - console.info('main.js finished') ipcRenderer.send('main.js finished') } catch (e) { diff --git a/packages/gui/src/utils/util.apppath.js b/packages/gui/src/utils/util.apppath.js index 0ee39d13b2..5e47fc24a6 100644 --- a/packages/gui/src/utils/util.apppath.js +++ b/packages/gui/src/utils/util.apppath.js @@ -1,6 +1,6 @@ import os from 'node:os' import path from 'node:path' -import log from './util.log.gui' +import log from './util.log.gui.js' function getSystemPlatform (throwIfUnknown = false) { switch (os.platform()) { diff --git a/packages/gui/src/utils/util.log.gui.js b/packages/gui/src/utils/util.log.gui.js index c95af6c22d..5167fe90a1 100644 --- a/packages/gui/src/utils/util.log.gui.js +++ b/packages/gui/src/utils/util.log.gui.js @@ -1,5 +1,5 @@ -const loggerFactory = require('@docmirror/dev-sidecar/src/utils/util.logger') +import loggerFactory from '@docmirror/dev-sidecar/src/utils/util.logger.js' const logger = loggerFactory.getLogger('gui') -module.exports = logger +export default logger diff --git a/packages/gui/src/view/App.vue b/packages/gui/src/view/App.vue index fa001e21ce..de21789538 100644 --- a/packages/gui/src/view/App.vue +++ b/packages/gui/src/view/App.vue @@ -1,12 +1,16 @@