diff --git a/packages/ui/src/common/prerequisite-step-by-step-check.ts b/packages/ui/src/common/prerequisite-step-by-step-check.ts index b36d9ca..1442ceb 100644 --- a/packages/ui/src/common/prerequisite-step-by-step-check.ts +++ b/packages/ui/src/common/prerequisite-step-by-step-check.ts @@ -1,17 +1,18 @@ -export const getAutoStartChatSteps = () => [{ - id: 'worker-launch', - describe: '启动子进程', -}, -// { -// id: 'basic-cookie-check', -// describe: 'Cookie 格式检查', -// }, -{ - id: 'puppeteer-executable-check', - describe: 'Puppeteer 可执行程序检查', -}, -{ - id: 'login-status-check', - describe: '登录状态检查', -} -] \ No newline at end of file +export const getAutoStartChatSteps = () => [ + { + id: 'worker-launch', + describe: '启动子进程' + }, + { + id: 'puppeteer-executable-check', + describe: 'Puppeteer 可执行程序检查' + }, + { + id: 'basic-cookie-check', + describe: 'Cookie 格式检查' + }, + { + id: 'login-status-check', + describe: '登录状态检查' + } +] diff --git a/packages/ui/src/main/features/login-with-cookie-assistant.ts b/packages/ui/src/main/features/login-with-cookie-assistant.ts new file mode 100644 index 0000000..03cb8b5 --- /dev/null +++ b/packages/ui/src/main/features/login-with-cookie-assistant.ts @@ -0,0 +1,21 @@ +import { ipcMain } from 'electron' +import { createCookieAssistantWindow, cookieAssistantWindow } from '../window/cookieAssistantWindow'; + +export async function loginWithCookieAssistant({ windowOption } = {}) { + return new Promise((resolve, reject) => { + createCookieAssistantWindow({ ...windowOption }) + + let processDone = false + ipcMain.once('cookie-saved', function handler() { + processDone = true + cookieAssistantWindow.close() + }) + cookieAssistantWindow.once('closed', () => { + if (processDone) { + resolve(true) + } else { + reject(new Error('User cancelled login')) + } + }) + }) +} diff --git a/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts b/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts index cc11b4e..d94bcdf 100644 --- a/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts +++ b/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts @@ -3,12 +3,10 @@ import path from 'path' import * as childProcess from 'node:child_process' import { ensureConfigFileExist, - ensureStorageFileExist, configFileNameList, readConfigFile, writeConfigFile, readStorageFile, - writeStorageFile, storageFilePath } from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs' import { ChildProcess } from 'child_process' @@ -54,6 +52,7 @@ import { checkUpdateForUi } from '../../../features/updater' import gtag from '../../../utils/gtag' import { daemonEE, sendToDaemon } from '../connect-to-daemon' import { runCommon } from '../../../features/run-common' +import { loginWithCookieAssistant } from '../../../features/login-with-cookie-assistant' export default function initIpc() { ipcMain.handle('fetch-config-file-content', async () => { @@ -189,17 +188,6 @@ export default function initIpc() { return await Promise.all(promiseArr) }) - ipcMain.handle('read-storage-file', async (ev, payload) => { - ensureStorageFileExist() - return await readStorageFile(payload.fileName) - }) - - ipcMain.handle('write-storage-file', async (ev, payload) => { - ensureStorageFileExist() - - return await writeStorageFile(payload.fileName, JSON.parse(payload.data)) - }) - ipcMain.handle('run-geek-auto-start-chat-with-boss', async (ev) => { const mode = 'geekAutoStartWithBossMain' const { runRecordId } = await runCommon({ mode }) @@ -395,56 +383,6 @@ export default function initIpc() { ) }) - let subProcessOfBossZhipinLoginPageWithPreloadExtension: ChildProcess | null = null - ipcMain.on('launch-bosszhipin-login-page-with-preload-extension', async () => { - try { - subProcessOfBossZhipinLoginPageWithPreloadExtension?.kill() - } catch { - // - } - const subProcessEnv = { - ...process.env, - PUPPETEER_EXECUTABLE_PATH: (await getAnyAvailablePuppeteerExecutable())!.executablePath - } - subProcessOfBossZhipinLoginPageWithPreloadExtension = childProcess.spawn( - process.argv[0], - [process.argv[1], `--mode=launchBossZhipinLoginPageWithPreloadExtension`], - { - env: subProcessEnv, - stdio: [null, null, null, 'pipe', 'ipc'] - } - ) - subProcessOfBossZhipinLoginPageWithPreloadExtension!.stdio[3]!.pipe(JSONStream.parse()).on( - 'data', - (raw) => { - const data = raw - switch (data.type) { - case 'BOSS_ZHIPIN_COOKIE_COLLECTED': { - mainWindow?.webContents.send(data.type, data) - break - } - default: { - return - } - } - } - ) - - subProcessOfBossZhipinLoginPageWithPreloadExtension!.once('exit', () => { - mainWindow?.webContents.send('BOSS_ZHIPIN_LOGIN_PAGE_CLOSED') - subProcessOfBossZhipinLoginPageWithPreloadExtension = null - }) - }) - ipcMain.on('kill-bosszhipin-login-page-with-preload-extension', async () => { - try { - subProcessOfBossZhipinLoginPageWithPreloadExtension?.kill() - } catch { - // - } finally { - subProcessOfBossZhipinLoginPageWithPreloadExtension = null - } - }) - ipcMain.handle('check-boss-zhipin-cookie-file', () => { const cookies = readStorageFile('boss-cookies.json') return checkCookieListFormat(cookies) @@ -666,6 +604,15 @@ export default function initIpc() { const newRelease = await checkUpdateForUi() return newRelease }) + ipcMain.handle('login-with-cookie-assistant', async () => { + return await loginWithCookieAssistant({ + windowOption: { + parent: mainWindow!, + modal: true, + show: true + } + }) + }) ipcMain.handle('exit-app-immediately', () => { app.exit(0) diff --git a/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER_MAIN/bootstrap.ts b/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER_MAIN/bootstrap.ts index 0b5ef97..1f3f7ce 100644 --- a/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER_MAIN/bootstrap.ts +++ b/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER_MAIN/bootstrap.ts @@ -7,8 +7,6 @@ import { setDomainLocalStorage } from '@geekgeekrun/utils/puppeteer/local-storag const localStoragePageUrl = `https://www.zhipin.com/desktop/` const bossChatUiUrl = `https://www.zhipin.com/web/geek/chat` -const bossCookies = readStorageFile('boss-cookies.json') -const bossLocalStorage = readStorageFile('boss-local-storage.json') export async function bootstrap() { const { puppeteer } = await initPuppeteer() @@ -28,6 +26,8 @@ export async function bootstrap() { export async function launchBoss(browser: Browser) { const page = (await browser.pages())[0] + const bossCookies = readStorageFile('boss-cookies.json') + const bossLocalStorage = readStorageFile('boss-local-storage.json') //set cookies for (let i = 0; i < bossCookies.length; i++) { await page.setCookie(bossCookies[i]) diff --git a/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER_MAIN/index.ts b/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER_MAIN/index.ts index 7655b8d..b7dcdac 100644 --- a/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER_MAIN/index.ts +++ b/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER_MAIN/index.ts @@ -16,19 +16,29 @@ import { getJobHireStatusRecord, saveJobHireStatusRecord } from '@geekgeekrun/sqlite-plugin/dist/handlers' -import { writeStorageFile } from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs' +import { + writeStorageFile, + readStorageFile +} from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs' import { BossInfo } from '@geekgeekrun/sqlite-plugin/dist/entity/BossInfo' import { messageForSaveFilter } from '../../../common/utils/chat-list' -import { AUTO_CHAT_ERROR_EXIT_CODE, RECHAT_CONTENT_SOURCE, RECHAT_LLM_FALLBACK } from '../../../common/enums/auto-start-chat' +import { + AUTO_CHAT_ERROR_EXIT_CODE, + RECHAT_CONTENT_SOURCE, + RECHAT_LLM_FALLBACK +} from '../../../common/enums/auto-start-chat' import gtag from '../../utils/gtag' import { JobHireStatus } from '@geekgeekrun/sqlite-plugin/dist/enums'; import dayjs from 'dayjs' import cheerio from 'cheerio' import { connectToDaemon, sendToDaemon } from '../OPEN_SETTING_WINDOW/connect-to-daemon' -import { pushCurrentPageScreenshot, SCREENSHOT_INTERVAL_MS } from '../../utils/screenshot' +// import { pushCurrentPageScreenshot, SCREENSHOT_INTERVAL_MS } from '../../utils/screenshot' import { checkShouldExit } from '../../utils/worker' import { getAnyAvailablePuppeteerExecutable } from '../CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable' import minimist from 'minimist' +import { checkCookieListFormat } from '../../../common/utils/cookie' +import { loginWithCookieAssistant } from '../../features/login-with-cookie-assistant' +import initPublicIpc from '../../utils/initPublicIpc' const throttleIntervalMinutes = readConfigFile('boss.json').autoReminder?.throttleIntervalMinutes ?? 10 @@ -232,6 +242,39 @@ const mainLoop = async () => { browser = null } } + let bossCookies = readStorageFile('boss-cookies.json') + let cookieCheckResult = checkCookieListFormat(bossCookies) + while (!cookieCheckResult) { + try { + await loginWithCookieAssistant() + bossCookies = readStorageFile('boss-cookies.json') + cookieCheckResult = checkCookieListFormat(bossCookies) + } catch (err) { + sendToDaemon({ + type: 'worker-to-gui-message', + data: { + type: 'prerequisite-step-by-step-checkstep-by-step-check', + step: { + id: 'basic-cookie-check', + status: 'rejected' + }, + runRecordId + } + }) + throw new Error('LOGIN_STATUS_INVALID') + } + } + sendToDaemon({ + type: 'worker-to-gui-message', + data: { + type: 'prerequisite-step-by-step-checkstep-by-step-check', + step: { + id: 'basic-cookie-check', + status: 'fulfilled' + }, + runRecordId + } + }) const canNotConfirmIfHasReadMsgTemplateList = [ 'Boss还没查看你的消息', '你与该职位竞争者PK情况', @@ -250,17 +293,6 @@ const mainLoop = async () => { // #region if (currentPageUrl.startsWith('https://www.zhipin.com/web/user/')) { writeStorageFile('boss-cookies.json', []) - sendToDaemon({ - type: 'worker-to-gui-message', - data: { - type: 'prerequisite-step-by-step-checkstep-by-step-check', - step: { - id: 'login-status-check', - status: 'rejected' - }, - runRecordId - } - }) throw new Error('LOGIN_STATUS_INVALID') } if ( @@ -526,6 +558,8 @@ const rerunInterval = (() => { const runRecordId = minimist(process.argv.slice(2))['run-record-id'] ?? null export async function runEntry() { app.dock?.hide() + await app.whenReady() + initPublicIpc() await connectToDaemon() await sendToDaemon({ type: 'ping' @@ -588,13 +622,29 @@ export async function runEntry() { // handle error if (err instanceof Error) { if (err.message.includes('LOGIN_STATUS_INVALID')) { - await dialog.showMessageBox({ - type: `error`, - message: `登录状态无效`, - detail: `请重新登录Boss直聘` - }) - process.exit(AUTO_CHAT_ERROR_EXIT_CODE.LOGIN_STATUS_INVALID) - break + try { + // popup login dialog, then update login status + await loginWithCookieAssistant() + } catch (err) { + await dialog.showMessageBox({ + type: `error`, + message: `登录状态无效`, + detail: `请重新登录Boss直聘` + }) + sendToDaemon({ + type: 'worker-to-gui-message', + data: { + type: 'prerequisite-step-by-step-checkstep-by-step-check', + step: { + id: 'login-status-check', + status: 'rejected' + }, + runRecordId + } + }) + process.exit(AUTO_CHAT_ERROR_EXIT_CODE.LOGIN_STATUS_INVALID) + break + } } if (err.message.includes('ERR_INTERNET_DISCONNECTED')) { process.exit(AUTO_CHAT_ERROR_EXIT_CODE.ERR_INTERNET_DISCONNECTED) @@ -656,3 +706,8 @@ async function storeStorage(page) { writeStorageFile('boss-local-storage.json', localStorage) ]) } + +process.on('SIGTERM', () => { + console.log('收到SIGTERM信号,正在退出') + process.exit(0) +}) diff --git a/packages/ui/src/main/utils/initPublicIpc.ts b/packages/ui/src/main/utils/initPublicIpc.ts index 94a75aa..f27496d 100644 --- a/packages/ui/src/main/utils/initPublicIpc.ts +++ b/packages/ui/src/main/utils/initPublicIpc.ts @@ -2,6 +2,11 @@ import { BrowserWindow, ipcMain, shell } from 'electron' import gtag from './gtag' import buildInfo from '../../common/build-info.json' import os from 'node:os' +import { + ensureStorageFileExist, + readStorageFile, + writeStorageFile +} from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs' export default function initPublicIpc() { ipcMain.on( @@ -56,4 +61,14 @@ export default function initPublicIpc() { } ) }) + + ipcMain.handle('read-storage-file', async (ev, payload) => { + ensureStorageFileExist() + return await readStorageFile(payload.fileName) + }) + + ipcMain.handle('write-storage-file', async (ev, payload) => { + ensureStorageFileExist() + return await writeStorageFile(payload.fileName, JSON.parse(payload.data)) + }) } diff --git a/packages/ui/src/main/window/cookieAssistantWindow.ts b/packages/ui/src/main/window/cookieAssistantWindow.ts new file mode 100644 index 0000000..dc927b7 --- /dev/null +++ b/packages/ui/src/main/window/cookieAssistantWindow.ts @@ -0,0 +1,106 @@ +import { ChildProcess } from 'child_process' +import { BrowserWindow, ipcMain } from 'electron' +import path from 'path' +import { getAnyAvailablePuppeteerExecutable } from '../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable' +import * as childProcess from 'node:child_process' +import * as JSONStream from 'JSONStream' + +export let cookieAssistantWindow: BrowserWindow | null = null +export function createCookieAssistantWindow( + opt?: Electron.BrowserWindowConstructorOptions +): BrowserWindow { + // Create the browser window. + if (cookieAssistantWindow) { + cookieAssistantWindow!.show() + } + cookieAssistantWindow = new BrowserWindow({ + width: 960, + height: 720, + resizable: true, + show: false, + autoHideMenuBar: true, + webPreferences: { + preload: path.join(__dirname, '../preload/index.js'), + sandbox: false + }, + ...opt + }) + + cookieAssistantWindow.on('ready-to-show', () => { + cookieAssistantWindow!.show() + }) + + // HMR for renderer base on electron-vite cli. + // Load the remote URL for development or the local html file for production. + if (process.env.NODE_ENV === 'development' && process.env['ELECTRON_RENDERER_URL']) { + cookieAssistantWindow.loadURL(process.env['ELECTRON_RENDERER_URL'] + '#/cookieAssistant') + } else { + cookieAssistantWindow.loadURL( + 'file://' + path.join(__dirname, '../renderer/index.html') + '#/cookieAssistant' + ) + } + + cookieAssistantWindow!.once('closed', () => { + cookieAssistantWindow = null + }) + + let subProcessOfBossZhipinLoginPageWithPreloadExtension: ChildProcess | null = null + const launchHandler = async () => { + try { + subProcessOfBossZhipinLoginPageWithPreloadExtension?.kill() + } catch { + // + } + const subProcessEnv = { + ...process.env, + PUPPETEER_EXECUTABLE_PATH: (await getAnyAvailablePuppeteerExecutable())!.executablePath + } + subProcessOfBossZhipinLoginPageWithPreloadExtension = childProcess.spawn( + process.argv[0], + [process.argv[1], `--mode=launchBossZhipinLoginPageWithPreloadExtension`], + { + env: subProcessEnv, + stdio: [null, null, null, 'pipe', 'ipc'] + } + ) + subProcessOfBossZhipinLoginPageWithPreloadExtension!.stdio[3]!.pipe(JSONStream.parse()).on( + 'data', + (raw) => { + const data = raw + switch (data.type) { + case 'BOSS_ZHIPIN_COOKIE_COLLECTED': { + cookieAssistantWindow?.webContents.send(data.type, data) + break + } + default: { + return + } + } + } + ) + + subProcessOfBossZhipinLoginPageWithPreloadExtension!.once('exit', () => { + cookieAssistantWindow?.webContents.send('BOSS_ZHIPIN_LOGIN_PAGE_CLOSED') + subProcessOfBossZhipinLoginPageWithPreloadExtension = null + }) + } + ipcMain.on('launch-bosszhipin-login-page-with-preload-extension', launchHandler) + + const killHandler = async () => { + try { + subProcessOfBossZhipinLoginPageWithPreloadExtension?.kill() + } catch { + // + } finally { + subProcessOfBossZhipinLoginPageWithPreloadExtension = null + } + } + ipcMain.on('kill-bosszhipin-login-page-with-preload-extension', killHandler) + cookieAssistantWindow.on('closed', () => { + subProcessOfBossZhipinLoginPageWithPreloadExtension?.kill() + ipcMain.off('launch-bosszhipin-login-page-with-preload-extension', launchHandler) + ipcMain.off('kill-bosszhipin-login-page-with-preload-extension', killHandler) + }) + + return cookieAssistantWindow! +} diff --git a/packages/ui/src/renderer/src/page/BootstrapSplash/index.vue b/packages/ui/src/renderer/src/page/BootstrapSplash/index.vue index d100754..422fe6c 100644 --- a/packages/ui/src/renderer/src/page/BootstrapSplash/index.vue +++ b/packages/ui/src/renderer/src/page/BootstrapSplash/index.vue @@ -4,56 +4,48 @@
愿你薪想事成
-
- -
diff --git a/packages/ui/src/renderer/src/page/BrowserAssistant/index.vue b/packages/ui/src/renderer/src/page/BrowserAssistant/index.vue new file mode 100644 index 0000000..1ab6a6b --- /dev/null +++ b/packages/ui/src/renderer/src/page/BrowserAssistant/index.vue @@ -0,0 +1,58 @@ + + + diff --git a/packages/ui/src/renderer/src/page/BootstrapSplash/page/DownloadingDependencies.vue b/packages/ui/src/renderer/src/page/BrowserAssistant/page/DownloadingDependencies.vue similarity index 100% rename from packages/ui/src/renderer/src/page/BootstrapSplash/page/DownloadingDependencies.vue rename to packages/ui/src/renderer/src/page/BrowserAssistant/page/DownloadingDependencies.vue diff --git a/packages/ui/src/renderer/src/page/BootstrapSplash/page/FailMessage.vue b/packages/ui/src/renderer/src/page/BrowserAssistant/page/FailMessage.vue similarity index 100% rename from packages/ui/src/renderer/src/page/BootstrapSplash/page/FailMessage.vue rename to packages/ui/src/renderer/src/page/BrowserAssistant/page/FailMessage.vue diff --git a/packages/ui/src/renderer/src/page/CookieAssistant/index.vue b/packages/ui/src/renderer/src/page/CookieAssistant/index.vue index 2df9a10..9c6be60 100644 --- a/packages/ui/src/renderer/src/page/CookieAssistant/index.vue +++ b/packages/ui/src/renderer/src/page/CookieAssistant/index.vue @@ -201,7 +201,7 @@ const handleEditThisCookieExtensionStoreLinkClick = () => { const handleCancel = () => { gtagRenderer('cancel_clicked') - router.replace('/main-layout') + window.close() } const handleSubmit = async () => { gtagRenderer('save_clicked') @@ -212,7 +212,8 @@ const handleSubmit = async () => { }) ElMessage.success('Boss直聘 Cookie 保存成功') gtagRenderer('save_cookie_done') - router.replace('/main-layout') + + window.electron.ipcRenderer.send('cookie-saved') } const handleBossZhipinLoginPageClosed = () => { diff --git a/packages/ui/src/renderer/src/page/MainLayout/GeekAutoStartChatWithBoss/index.vue b/packages/ui/src/renderer/src/page/MainLayout/GeekAutoStartChatWithBoss/index.vue index 9171a5c..4aa8c9a 100644 --- a/packages/ui/src/renderer/src/page/MainLayout/GeekAutoStartChatWithBoss/index.vue +++ b/packages/ui/src/renderer/src/page/MainLayout/GeekAutoStartChatWithBoss/index.vue @@ -1001,7 +1001,7 @@ pr50px pb30px class="no-active-definition-text-slider" - + :format-tooltip=" (v) => typeof noActiveDefinitionMarks[v] === 'string' @@ -1535,9 +1535,17 @@ const normalizeExpectCompanies = () => { .join(',') } -const handleClickLaunchLogin = () => { +const handleClickLaunchLogin = async () => { gtagRenderer('launch_login_clicked') - router.replace('/cookieAssistant') + try { + await electron.ipcRenderer.invoke('login-with-cookie-assistant') + ElMessage({ + type: 'success', + message: 'Cookie 保存成功' + }) + } catch { + // + } } const expectCompanyTemplateList = [ { diff --git a/packages/ui/src/renderer/src/page/MainLayout/ReadNoReplyReminder.vue b/packages/ui/src/renderer/src/page/MainLayout/ReadNoReplyReminder.vue index 0348a5c..1f76d75 100644 --- a/packages/ui/src/renderer/src/page/MainLayout/ReadNoReplyReminder.vue +++ b/packages/ui/src/renderer/src/page/MainLayout/ReadNoReplyReminder.vue @@ -526,9 +526,17 @@ const restoreDefaultTemplate = async () => { }) } -const handleClickLaunchLogin = () => { +const handleClickLaunchLogin = async () => { gtagRenderer('launch_login_clicked') - router.replace('/cookieAssistant') + try { + await electron.ipcRenderer.invoke('login-with-cookie-assistant') + ElMessage({ + type: 'success', + message: 'Cookie 保存成功' + }) + } catch { + // + } } const currentStamp = ref(new Date()) diff --git a/packages/ui/src/renderer/src/page/MainLayout/index.vue b/packages/ui/src/renderer/src/page/MainLayout/index.vue index 780b079..c9f4b31 100644 --- a/packages/ui/src/renderer/src/page/MainLayout/index.vue +++ b/packages/ui/src/renderer/src/page/MainLayout/index.vue @@ -164,28 +164,12 @@ onUnmounted(() => { } catch {} } }) -const goToCheckBossZhipinCookieFile = () => router.replace('/cookieAssistant') -onMounted(() => { - electron.ipcRenderer.on('check-boss-zhipin-cookie-file', goToCheckBossZhipinCookieFile) -}) -onUnmounted(() => { - electron.ipcRenderer.removeListener( - 'check-boss-zhipin-cookie-file', - goToCheckBossZhipinCookieFile - ) -}) ;(async () => { const checkDependenciesResult = await electron.ipcRenderer.invoke('check-dependencies') if (Object.values(checkDependenciesResult).includes(false)) { router.replace('/') return } - - const isCookieFileValid = await electron.ipcRenderer.invoke('check-boss-zhipin-cookie-file') - if (!isCookieFileValid) { - router.replace('/cookieAssistant') - return - } })() const { buildInfo } = useBuildInfo() diff --git a/packages/ui/src/renderer/src/router/index.ts b/packages/ui/src/renderer/src/router/index.ts index d3b68c2..c7dcaa1 100644 --- a/packages/ui/src/renderer/src/router/index.ts +++ b/packages/ui/src/renderer/src/router/index.ts @@ -17,6 +17,22 @@ const routes: Array = [ title: 'Boss 登录助手' } }, + { + path: '/browserAssistant', + component: () => import('@renderer/page/BrowserAssistant/index.vue'), + meta: { + title: '浏览器助手' + }, + children: [ + { + path: '/downloadingDependencies', + component: () => import('@renderer/page/BrowserAssistant/page/DownloadingDependencies.vue'), + meta: { + title: '正在下载核心组件' + } + } + ] + }, { path: '/llmConfig', component: () => import('@renderer/page/LlmConfig/index.vue'), @@ -136,16 +152,7 @@ const routes: Array = [ component: BootstrapSplash, meta: { title: '薪想事成' - }, - children: [ - { - path: '/downloadingDependencies', - component: () => import('@renderer/page/BootstrapSplash/page/DownloadingDependencies.vue'), - meta: { - title: '正在下载核心组件' - } - } - ] + } } ]