mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-05-24 17:50:13 +08:00
add browser assistant entry on ui
This commit is contained in:
@@ -1 +1,2 @@
|
||||
export const SINGLE_ITEM_DEFAULT_SERVE_WEIGHT = 1
|
||||
export const EXPECT_CHROMIUM_BUILD_ID = '139.0.7258.154'
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { ipcMain } from 'electron'
|
||||
import {
|
||||
createBrowserAssistantWindow,
|
||||
browserAssistantWindow
|
||||
} from '../window/browserAssistantWindow'
|
||||
|
||||
export async function configWithBrowserAssistant({ windowOption } = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
createBrowserAssistantWindow({ ...windowOption })
|
||||
|
||||
let processDone = false
|
||||
function handler() {
|
||||
processDone = true
|
||||
browserAssistantWindow.close()
|
||||
}
|
||||
ipcMain.once('browser-config-saved', handler)
|
||||
browserAssistantWindow.once('closed', () => {
|
||||
ipcMain.off('browser-config-saved', handler)
|
||||
if (processDone) {
|
||||
resolve(true)
|
||||
} else {
|
||||
reject(new Error('USER_CANCELLED_CONFIG_BROWSER'))
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -6,11 +6,13 @@ export async function loginWithCookieAssistant({ windowOption } = {}) {
|
||||
createCookieAssistantWindow({ ...windowOption })
|
||||
|
||||
let processDone = false
|
||||
ipcMain.once('cookie-saved', function handler() {
|
||||
function handler() {
|
||||
processDone = true
|
||||
cookieAssistantWindow.close()
|
||||
})
|
||||
}
|
||||
ipcMain.once('cookie-saved', handler)
|
||||
cookieAssistantWindow.once('closed', () => {
|
||||
ipcMain.off('cookie-saved', handler)
|
||||
if (processDone) {
|
||||
resolve(true)
|
||||
} else {
|
||||
|
||||
@@ -40,13 +40,6 @@ export const getLastUsedAndAvailableBrowser = async (): Promise<BrowserInfo | nu
|
||||
await removeLastUsedAndAvailableBrowserPath()
|
||||
return null
|
||||
}
|
||||
|
||||
// blacklist browser
|
||||
if (path.includes(`Microsoft\\Edge\\Application\\msedge.exe`)) {
|
||||
await removeLastUsedAndAvailableBrowserPath()
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
executablePath: path,
|
||||
browser
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
removeLastUsedAndAvailableBrowserPath
|
||||
} from '../browser-history'
|
||||
import gtag from '../../../../utils/gtag'
|
||||
import { EXPECT_CHROMIUM_BUILD_ID } from '../../../../../common/constant'
|
||||
|
||||
const getPuppeteerManagerModule = async () => {
|
||||
const puppeteerManager = await import('@puppeteer/browsers')
|
||||
@@ -16,7 +17,6 @@ const getPuppeteerManagerModule = async () => {
|
||||
return puppeteerManager
|
||||
}
|
||||
|
||||
const EXPECT_CHROMIUM_BUILD_ID = '139.0.7258.154'
|
||||
const cacheDir = path.join(os.homedir(), '.geekgeekrun', 'cache')
|
||||
|
||||
const getExpectCachedPuppeteerExecutable = async (): Promise<BrowserInfo> => {
|
||||
@@ -97,29 +97,36 @@ export const checkAndDownloadPuppeteerExecutable = async (
|
||||
return installedBrowser
|
||||
}
|
||||
|
||||
export const getAnyAvailablePuppeteerExecutable = async (): Promise<BrowserInfo | null> => {
|
||||
const lastUsedOne = await getLastUsedAndAvailableBrowser()
|
||||
if (lastUsedOne) {
|
||||
return lastUsedOne
|
||||
export const getAnyAvailablePuppeteerExecutable = async ({
|
||||
ignoreCached = false,
|
||||
noSave = false
|
||||
}: {
|
||||
ignoreCached?: boolean
|
||||
noSave?: boolean
|
||||
} = {}): Promise<BrowserInfo | null> => {
|
||||
if (!ignoreCached) {
|
||||
const lastUsedOne = await getLastUsedAndAvailableBrowser()
|
||||
if (lastUsedOne) {
|
||||
return lastUsedOne
|
||||
}
|
||||
}
|
||||
// find existed browser - the fallback one
|
||||
if (await checkCachedPuppeteerExecutable()) {
|
||||
const cachedOne = await getExpectCachedPuppeteerExecutable()
|
||||
!noSave && (await saveLastUsedAndAvailableBrowserInfo(cachedOne))
|
||||
|
||||
return cachedOne
|
||||
}
|
||||
// find existed browser - the one maybe actively installed by user or ship with os like Edge on windows
|
||||
try {
|
||||
const existedOne = await findAndLocateUserInstalledChromiumExecutableSync()
|
||||
await saveLastUsedAndAvailableBrowserInfo(existedOne)
|
||||
!noSave && (await saveLastUsedAndAvailableBrowserInfo(existedOne))
|
||||
// save its path
|
||||
return existedOne
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
console.log('no existed browser path found')
|
||||
}
|
||||
// find existed browser - the fallback one
|
||||
if (await checkCachedPuppeteerExecutable()) {
|
||||
const cachedOne = await getExpectCachedPuppeteerExecutable()
|
||||
await saveLastUsedAndAvailableBrowserInfo(cachedOne)
|
||||
|
||||
return cachedOne
|
||||
}
|
||||
|
||||
// if no one available, then return null and remove last used browser
|
||||
await removeLastUsedAndAvailableBrowserPath()
|
||||
return null
|
||||
|
||||
@@ -53,6 +53,7 @@ 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'
|
||||
import { configWithBrowserAssistant } from '../../../features/config-with-browser-assistant'
|
||||
|
||||
export default function initIpc() {
|
||||
ipcMain.handle('fetch-config-file-content', async () => {
|
||||
@@ -246,64 +247,6 @@ export default function initIpc() {
|
||||
return { runRecordId }
|
||||
})
|
||||
|
||||
ipcMain.handle('check-dependencies', async () => {
|
||||
const [anyAvailablePuppeteerExecutable] = await Promise.all([
|
||||
getAnyAvailablePuppeteerExecutable()
|
||||
])
|
||||
return {
|
||||
puppeteerExecutableAvailable: !!anyAvailablePuppeteerExecutable
|
||||
}
|
||||
})
|
||||
|
||||
let subProcessOfCheckAndDownloadDependencies: ChildProcess | null = null
|
||||
ipcMain.handle('setup-dependencies', async () => {
|
||||
if (subProcessOfCheckAndDownloadDependencies) {
|
||||
return
|
||||
}
|
||||
subProcessOfCheckAndDownloadDependencies = childProcess.spawn(
|
||||
process.argv[0],
|
||||
[process.argv[1], `--mode=checkAndDownloadDependenciesForInit`],
|
||||
{
|
||||
stdio: [null, null, null, 'pipe', 'ipc']
|
||||
}
|
||||
)
|
||||
return new Promise((resolve, reject) => {
|
||||
subProcessOfCheckAndDownloadDependencies!.stdio[3]!.pipe(JSONStream.parse()).on(
|
||||
'data',
|
||||
(raw) => {
|
||||
const data = raw
|
||||
switch (data.type) {
|
||||
case 'NEED_RESETUP_DEPENDENCIES':
|
||||
case 'PUPPETEER_DOWNLOAD_PROGRESS': {
|
||||
mainWindow?.webContents.send(data.type, data)
|
||||
break
|
||||
}
|
||||
case 'PUPPETEER_DOWNLOAD_ENCOUNTER_ERROR': {
|
||||
console.error(data)
|
||||
break
|
||||
}
|
||||
default: {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
subProcessOfCheckAndDownloadDependencies!.once('exit', (exitCode) => {
|
||||
switch (exitCode) {
|
||||
case 0: {
|
||||
resolve(exitCode)
|
||||
break
|
||||
}
|
||||
default: {
|
||||
reject('PUPPETEER_DOWNLOAD_ENCOUNTER_ERROR')
|
||||
break
|
||||
}
|
||||
}
|
||||
subProcessOfCheckAndDownloadDependencies = null
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
ipcMain.handle('stop-geek-auto-start-chat-with-boss', async () => {
|
||||
mainWindow?.webContents.send('geek-auto-start-chat-with-boss-stopping')
|
||||
const p = new Promise((resolve) => {
|
||||
@@ -613,6 +556,15 @@ export default function initIpc() {
|
||||
}
|
||||
})
|
||||
})
|
||||
ipcMain.handle('config-with-browser-assistant', async () => {
|
||||
return await configWithBrowserAssistant({
|
||||
windowOption: {
|
||||
parent: mainWindow!,
|
||||
modal: true,
|
||||
show: true
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
ipcMain.handle('exit-app-immediately', () => {
|
||||
app.exit(0)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BrowserWindow, ipcMain, shell } from 'electron'
|
||||
import { BrowserWindow, dialog, ipcMain, shell } from 'electron'
|
||||
import gtag from './gtag'
|
||||
import buildInfo from '../../common/build-info.json'
|
||||
import os from 'node:os'
|
||||
@@ -71,4 +71,18 @@ export default function initPublicIpc() {
|
||||
ensureStorageFileExist()
|
||||
return await writeStorageFile(payload.fileName, JSON.parse(payload.data))
|
||||
})
|
||||
ipcMain.handle('get-os-platform', () => {
|
||||
return os.platform()
|
||||
})
|
||||
ipcMain.handle('choose-file', (ev, { fileChooserConfig }) => {
|
||||
if (!fileChooserConfig) {
|
||||
fileChooserConfig = {}
|
||||
}
|
||||
const win = BrowserWindow.fromWebContents(ev.sender)
|
||||
if (!win) {
|
||||
return dialog.showOpenDialog(fileChooserConfig)
|
||||
} else {
|
||||
return dialog.showOpenDialog(win, fileChooserConfig)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
149
packages/ui/src/main/window/browserAssistantWindow.ts
Normal file
149
packages/ui/src/main/window/browserAssistantWindow.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
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'
|
||||
import {
|
||||
getLastUsedAndAvailableBrowser,
|
||||
saveLastUsedAndAvailableBrowserInfo
|
||||
} from '../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/browser-history'
|
||||
|
||||
export let browserAssistantWindow: BrowserWindow | null = null
|
||||
|
||||
const registerHandleWithWindow = (
|
||||
win: BrowserWindow,
|
||||
...args: Parameters<typeof ipcMain.handle>
|
||||
) => {
|
||||
const [channel, handler] = args
|
||||
ipcMain.handle(channel, handler)
|
||||
win.once('closed', () => ipcMain.removeHandler(channel))
|
||||
}
|
||||
|
||||
export function createBrowserAssistantWindow(
|
||||
opt?: Electron.BrowserWindowConstructorOptions
|
||||
): BrowserWindow {
|
||||
// Create the browser window.
|
||||
if (browserAssistantWindow) {
|
||||
browserAssistantWindow!.close()
|
||||
}
|
||||
browserAssistantWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
minWidth: 800,
|
||||
height: 400,
|
||||
resizable: true,
|
||||
show: false,
|
||||
autoHideMenuBar: true,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, '../preload/index.js'),
|
||||
sandbox: false
|
||||
},
|
||||
...opt
|
||||
})
|
||||
|
||||
browserAssistantWindow.on('ready-to-show', () => {
|
||||
browserAssistantWindow!.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']) {
|
||||
browserAssistantWindow.loadURL(process.env['ELECTRON_RENDERER_URL'] + '#/browserAssistant')
|
||||
} else {
|
||||
browserAssistantWindow.loadURL(
|
||||
'file://' + path.join(__dirname, '../renderer/index.html') + '#/browserAssistant'
|
||||
)
|
||||
}
|
||||
|
||||
browserAssistantWindow!.once('closed', () => {
|
||||
browserAssistantWindow = null
|
||||
})
|
||||
|
||||
registerHandleWithWindow(
|
||||
browserAssistantWindow,
|
||||
'get-any-available-puppeteer-executable',
|
||||
async (_, { ignoreCached, noSave } = {}) => {
|
||||
return await getAnyAvailablePuppeteerExecutable({ ignoreCached, noSave })
|
||||
}
|
||||
)
|
||||
|
||||
registerHandleWithWindow(
|
||||
browserAssistantWindow,
|
||||
'get-last-used-and-available-browser',
|
||||
async () => {
|
||||
return await getLastUsedAndAvailableBrowser()
|
||||
}
|
||||
)
|
||||
|
||||
registerHandleWithWindow(
|
||||
browserAssistantWindow,
|
||||
'save-last-used-and-available-browser-info',
|
||||
async (_, payload) => {
|
||||
return await saveLastUsedAndAvailableBrowserInfo(payload)
|
||||
}
|
||||
)
|
||||
|
||||
let subProcessOfCheckAndDownloadDependencies: ChildProcess | null = null
|
||||
registerHandleWithWindow(browserAssistantWindow, 'setup-dependencies', async () => {
|
||||
if (subProcessOfCheckAndDownloadDependencies) {
|
||||
return
|
||||
}
|
||||
subProcessOfCheckAndDownloadDependencies = childProcess.spawn(
|
||||
process.argv[0],
|
||||
[process.argv[1], `--mode=checkAndDownloadDependenciesForInit`],
|
||||
{
|
||||
stdio: [null, null, null, 'pipe', 'ipc']
|
||||
}
|
||||
)
|
||||
return new Promise((resolve, reject) => {
|
||||
subProcessOfCheckAndDownloadDependencies!.stdio[3]!.pipe(JSONStream.parse()).on(
|
||||
'data',
|
||||
(raw) => {
|
||||
const data = raw
|
||||
switch (data.type) {
|
||||
case 'NEED_RESETUP_DEPENDENCIES':
|
||||
case 'PUPPETEER_DOWNLOAD_PROGRESS': {
|
||||
browserAssistantWindow?.webContents.send(data.type, data)
|
||||
break
|
||||
}
|
||||
case 'PUPPETEER_DOWNLOAD_ENCOUNTER_ERROR': {
|
||||
console.error(data)
|
||||
break
|
||||
}
|
||||
default: {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
subProcessOfCheckAndDownloadDependencies!.once('exit', (exitCode) => {
|
||||
switch (exitCode) {
|
||||
case 0: {
|
||||
resolve(exitCode)
|
||||
break
|
||||
}
|
||||
default: {
|
||||
reject('PUPPETEER_DOWNLOAD_ENCOUNTER_ERROR')
|
||||
break
|
||||
}
|
||||
}
|
||||
subProcessOfCheckAndDownloadDependencies = null
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const killHandler = async () => {
|
||||
try {
|
||||
subProcessOfCheckAndDownloadDependencies?.kill()
|
||||
} catch {
|
||||
//
|
||||
} finally {
|
||||
subProcessOfCheckAndDownloadDependencies = null
|
||||
}
|
||||
}
|
||||
browserAssistantWindow.once('closed', () => {
|
||||
killHandler()
|
||||
})
|
||||
|
||||
return browserAssistantWindow!
|
||||
}
|
||||
@@ -27,25 +27,7 @@ const router = useRouter()
|
||||
|
||||
onMounted(async () => {
|
||||
gtagRenderer('bootstrap_mounted')
|
||||
// checkDependenciesResult.value = await electron.ipcRenderer.invoke('check-dependencies')
|
||||
// downloadProcessWaitee.value = Promise.withResolvers()
|
||||
|
||||
// if (Object.values(checkDependenciesResult.value).includes(false)) {
|
||||
// gtagRenderer('dependencies_need_download')
|
||||
// router.replace('/downloadingDependencies')
|
||||
// } else {
|
||||
// downloadProcessWaitee.value!.resolve()
|
||||
// }
|
||||
|
||||
// downloadProcessWaitee.value!.promise.then(async () => {
|
||||
// const isCookieFileValid = await electron.ipcRenderer.invoke('check-boss-zhipin-cookie-file')
|
||||
// if (!isCookieFileValid) {
|
||||
// gtagRenderer('found_cookie_invalid_when_bootstrap')
|
||||
// router.replace('/cookieAssistant')
|
||||
// } else {
|
||||
await sleep(2000)
|
||||
router.replace('/main-layout')
|
||||
// }
|
||||
// })
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,58 +1,200 @@
|
||||
<template>
|
||||
<div class="h-screen flex flex-col flex-items-center flex-justify-center">
|
||||
<div>
|
||||
<img
|
||||
class="block"
|
||||
:class="{
|
||||
'animate__animated animate__bounce animate__repeat-3':
|
||||
Object.values(checkDependenciesResult).includes(false)
|
||||
}"
|
||||
:width="256"
|
||||
src="@renderer/../../../resources/icon.png"
|
||||
/>
|
||||
<div class="h-screen of-hidden flex flex-col flex-items-center flex-justify-between">
|
||||
<div flex-1 of-hidden w-full>
|
||||
<el-form ref="formRef" :model="formData" :rules="rules" flex flex-col of-hidden h-full>
|
||||
<div class="bg-#f6f6f6" flex-0>
|
||||
<el-form-item
|
||||
class="w-80%"
|
||||
label="浏览器可执行文件路径"
|
||||
prop="browserPath"
|
||||
pt50px
|
||||
pb50px
|
||||
ml-auto
|
||||
mr-auto
|
||||
mb-0
|
||||
>
|
||||
<div flex flex-1>
|
||||
<el-input v-model="formData.browserPath" />
|
||||
<el-button type="primary" @click="autoDetectPuppeteerExecutable">自动检测</el-button>
|
||||
<el-button :style="{ marginLeft: 0 }" @click="browserExecutableFile">浏览</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div flex-1 of-auto font-size-14px line-height-1.5em>
|
||||
<div mt10px ml-auto mr-auto class="w-80%">
|
||||
<div>常见问题</div>
|
||||
<div>
|
||||
<details>
|
||||
<summary>不能自动检测到浏览器?</summary>
|
||||
<div ml12px class="color-#666">
|
||||
请尝试如下方案之一来处理:
|
||||
<ul pl1em m0>
|
||||
<li>
|
||||
方案一:通过本程序下载 Google Chrome for Testing
|
||||
{{ EXPECT_CHROMIUM_BUILD_ID }} -
|
||||
<a href="javascript:;">点击此处</a
|
||||
>即可下载;这个浏览器由本程序独占,不会影响到当前的 Google Chrome
|
||||
安装。本程序开发过程中主要是使用这个浏览器测试的,<span color-orange
|
||||
>可以保证兼容性</span
|
||||
>。但网络波动,有一定概率下载失败。如多次尝试后确实不能下载成功,请尝试方案二。<span
|
||||
color-orange
|
||||
>(推荐)</span
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
方案二:手动安装 Google Chrome 最新版本 -
|
||||
<a href="javascript:;" @click="handleOpenChromeDownloadPage">点击此处</a>打开
|
||||
Google Chrome
|
||||
官方网站,找到浏览器下载页面来下载安装程序。下载完毕后,执行安装程序。安装完成后,点击上方<a
|
||||
href="javascript:;"
|
||||
@click="autoDetectPuppeteerExecutable"
|
||||
>自动检测</a
|
||||
>按钮再次尝试。目前(2026.2.7)已知 Chrome 最新版本为 144.0.7559.133
|
||||
,多数情况下本程序都可以正常工作,但由于浏览器会自动升级,版本不固定,可能存在<span color-orange
|
||||
>浏览器升级后某些功能不兼容导致本程序不能正确运行</span
|
||||
>的问题。您可以<a href="javascript:;" @click="handleFeedbackClick"
|
||||
>提交 Issue</a
|
||||
>来反馈新版本浏览器不能正常运行的问题,同时请再尝试方法一。
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
<div mt24px>愿你薪想事成</div>
|
||||
<div class="h60px mt14px">
|
||||
<div class="bg-#f8f8f8 pb10px pt10px w-full flex-0">
|
||||
<div
|
||||
:style="{
|
||||
display: 'flex',
|
||||
justifyContent: 'end',
|
||||
width: '80%',
|
||||
margin: '0 auto',
|
||||
paddingLeft: '',
|
||||
paddingRight: ''
|
||||
}"
|
||||
>
|
||||
<el-button @click="handleCancel">取消</el-button>
|
||||
<el-button type="primary" @click="handleSave">确定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="h60px mt14px">
|
||||
<RouterView
|
||||
class="h100%"
|
||||
:dependencies-status="checkDependenciesResult"
|
||||
:process-waitee="downloadProcessWaitee"
|
||||
></RouterView>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useRouter } from 'vue-router'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { sleep } from '@geekgeekrun/utils/sleep.mjs'
|
||||
import { gtagRenderer } from '@renderer/utils/gtag'
|
||||
import { ref } from 'vue'
|
||||
import debounce from 'lodash/debounce'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { gtagRenderer as baseGtagRenderer } from '@renderer/utils/gtag'
|
||||
import { EXPECT_CHROMIUM_BUILD_ID } from '../../../../common/constant'
|
||||
|
||||
const router = useRouter()
|
||||
const { ipcRenderer } = electron
|
||||
useRouter()
|
||||
// const checkDependenciesResult = ref({})
|
||||
// const downloadProcessWaitee = ref(null)
|
||||
|
||||
const checkDependenciesResult = ref({})
|
||||
const downloadProcessWaitee = ref(null)
|
||||
const gtagRenderer = (name, params?: object) => {
|
||||
return baseGtagRenderer(name, {
|
||||
scene: 'cookie-assistant',
|
||||
...params
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
checkDependenciesResult.value = await electron.ipcRenderer.invoke('check-dependencies')
|
||||
downloadProcessWaitee.value = Promise.withResolvers()
|
||||
const handleOpenChromeDownloadPage = debounce(
|
||||
async () => {
|
||||
gtagRenderer('open_chrome_download_page_clicked')
|
||||
ipcRenderer.send('open-external-link', 'https://www.google.cn/chrome/')
|
||||
},
|
||||
1000,
|
||||
{ leading: true, trailing: false }
|
||||
)
|
||||
|
||||
if (Object.values(checkDependenciesResult.value).includes(false)) {
|
||||
gtagRenderer('dependencies_need_download')
|
||||
router.replace('/downloadingDependencies')
|
||||
} else {
|
||||
downloadProcessWaitee.value!.resolve()
|
||||
const formData = ref({
|
||||
browserPath: ''
|
||||
})
|
||||
|
||||
const rules = {
|
||||
browserPath: {
|
||||
validator: (_, value, callback) => {
|
||||
if (!value?.trim()) {
|
||||
callback(new Error('请输入浏览器可执行文件路径'))
|
||||
}
|
||||
// TODO: 检查文件是否存在
|
||||
else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
downloadProcessWaitee.value!.promise.then(async () => {
|
||||
const isCookieFileValid = await electron.ipcRenderer.invoke('check-boss-zhipin-cookie-file')
|
||||
if (!isCookieFileValid) {
|
||||
gtagRenderer('found_cookie_invalid_when_bootstrap')
|
||||
router.replace('/cookieAssistant')
|
||||
} else {
|
||||
await sleep(1000)
|
||||
router.replace('/main-layout')
|
||||
async function autoDetectPuppeteerExecutable() {
|
||||
const result = await ipcRenderer.invoke('get-any-available-puppeteer-executable', {
|
||||
ignoreCached: true,
|
||||
noSave: true
|
||||
})
|
||||
if (!result) {
|
||||
ElMessage.warning({
|
||||
message: '未检测到可用浏览器的可执行文件',
|
||||
type: 'warning'
|
||||
})
|
||||
return
|
||||
}
|
||||
formData.value.browserPath = result.executablePath
|
||||
}
|
||||
|
||||
async function browserExecutableFile() {
|
||||
const chooseResult = await ipcRenderer.invoke('choose-file', {
|
||||
fileChooserConfig: {
|
||||
properties: ['openFile', 'treatPackageAsDirectory'],
|
||||
filters: [
|
||||
{
|
||||
name: '可执行文件',
|
||||
extensions: (await ipcRenderer.invoke('get-os-platform')) === 'win32' ? ['exe'] : ['']
|
||||
},
|
||||
{ name: '所有文件', extensions: ['*'] }
|
||||
]
|
||||
}
|
||||
})
|
||||
if (chooseResult.canceled || !chooseResult.filePaths?.length) {
|
||||
return
|
||||
}
|
||||
formData.value.browserPath = chooseResult.filePaths[0]
|
||||
}
|
||||
|
||||
ipcRenderer.invoke('get-last-used-and-available-browser').then((res) => {
|
||||
formData.value.browserPath = res?.executablePath ?? ''
|
||||
})
|
||||
function handleCancel() {
|
||||
gtagRenderer('cancel_clicked')
|
||||
window.close()
|
||||
}
|
||||
async function handleSave() {
|
||||
await ipcRenderer.invoke('save-last-used-and-available-browser-info', {
|
||||
executablePath: formData.value.browserPath,
|
||||
browser: ''
|
||||
})
|
||||
await ipcRenderer.send('browser-config-saved')
|
||||
}
|
||||
const handleFeedbackClick = () => {
|
||||
gtagRenderer('goto_feedback_for_ba_clicked')
|
||||
electron.ipcRenderer.send('send-feed-back-to-github-issue')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
a:link,
|
||||
a:visited,
|
||||
a:hover,
|
||||
a:active {
|
||||
color: #409eff;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -10,16 +10,27 @@
|
||||
<div class="form-wrap geek-auto-start-run-with-boss">
|
||||
<el-form ref="formRef" :model="formContent" label-position="top" :rules="formRules">
|
||||
<el-card class="config-section">
|
||||
<el-form-item>
|
||||
<div>
|
||||
<div font-size-16px>BOSS直聘 Cookie</div>
|
||||
<el-button size="small" type="primary" @click="handleClickLaunchLogin"
|
||||
>编辑Cookie</el-button
|
||||
>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<div flex>
|
||||
<el-form-item>
|
||||
<div>
|
||||
<div font-size-14px>BOSS直聘 Cookie</div>
|
||||
<el-button size="small" type="primary" @click="handleClickLaunchLogin"
|
||||
>编辑Cookie</el-button
|
||||
>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<div w1px class="bg-#dee1e8" ml16px mr16px />
|
||||
<el-form-item>
|
||||
<div>
|
||||
<div font-size-14px>浏览器</div>
|
||||
<el-button size="small" type="primary" @click="handleClickBrowserSetting"
|
||||
>编辑浏览器设置</el-button
|
||||
>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div>
|
||||
<div font-size-16px>
|
||||
<div font-size-14px>
|
||||
摸鱼模式
|
||||
<el-tooltip
|
||||
effect="light"
|
||||
@@ -51,7 +62,7 @@
|
||||
启用摸鱼模式
|
||||
</el-checkbox>
|
||||
</div>
|
||||
<div pl-1.5em font-size-14px>
|
||||
<div pl-1.5em font-size-12px>
|
||||
<div
|
||||
:style="{
|
||||
color: formContent.isSageTimeEnabled ? '' : '#aaa'
|
||||
@@ -1602,6 +1613,20 @@ const handleClickLaunchLogin = async () => {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
const handleClickBrowserSetting = async () => {
|
||||
gtagRenderer('browser_setting_clicked')
|
||||
try {
|
||||
await electron.ipcRenderer.invoke('config-with-browser-assistant')
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '浏览器设置保存成功'
|
||||
})
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
const expectCompanyTemplateList = [
|
||||
{
|
||||
name: '默认值',
|
||||
|
||||
@@ -7,11 +7,19 @@
|
||||
:model="formContent.autoReminder"
|
||||
label-position="top"
|
||||
>
|
||||
<el-form-item label="BOSS直聘 Cookie">
|
||||
<el-button size="small" type="primary" @click="handleClickLaunchLogin"
|
||||
>编辑Cookie</el-button
|
||||
>
|
||||
</el-form-item>
|
||||
<div flex>
|
||||
<el-form-item label="BOSS直聘 Cookie">
|
||||
<el-button size="small" type="primary" @click="handleClickLaunchLogin"
|
||||
>编辑Cookie</el-button
|
||||
>
|
||||
</el-form-item>
|
||||
<div w1px class="bg-#dee1e8" ml16px mr16px />
|
||||
<el-form-item label="浏览器">
|
||||
<el-button size="small" type="primary" @click="handleClickBrowserSetting"
|
||||
>编辑浏览器设置</el-button
|
||||
>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item>
|
||||
<div>
|
||||
<el-checkbox v-if="!expectJobTypeRegExpStr?.trim()" :model-value="false" disabled>
|
||||
@@ -538,6 +546,18 @@ const handleClickLaunchLogin = async () => {
|
||||
//
|
||||
}
|
||||
}
|
||||
const handleClickBrowserSetting = async () => {
|
||||
gtagRenderer('browser_setting_clicked')
|
||||
try {
|
||||
await electron.ipcRenderer.invoke('config-with-browser-assistant')
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '浏览器设置保存成功'
|
||||
})
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
const currentStamp = ref(new Date())
|
||||
let timer = 0
|
||||
|
||||
@@ -146,7 +146,6 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { TopRight, QuestionFilled } from '@element-plus/icons-vue'
|
||||
import useBuildInfo from '@renderer/hooks/useBuildInfo'
|
||||
@@ -154,23 +153,7 @@ import { debounce } from 'lodash'
|
||||
import { gtagRenderer } from '@renderer/utils/gtag'
|
||||
import { useUpdateStore, useTaskManagerStore } from '../../store/index'
|
||||
|
||||
const router = useRouter()
|
||||
const unmountedCbs: Array<InstanceType<typeof Function>> = []
|
||||
onUnmounted(() => {
|
||||
while (unmountedCbs.length) {
|
||||
const fn = unmountedCbs.shift()!
|
||||
try {
|
||||
fn()
|
||||
} catch {}
|
||||
}
|
||||
})
|
||||
;(async () => {
|
||||
const checkDependenciesResult = await electron.ipcRenderer.invoke('check-dependencies')
|
||||
if (Object.values(checkDependenciesResult).includes(false)) {
|
||||
router.replace('/')
|
||||
return
|
||||
}
|
||||
})()
|
||||
useRouter()
|
||||
|
||||
const { buildInfo } = useBuildInfo()
|
||||
const handleFeedbackClick = () => {
|
||||
|
||||
Reference in New Issue
Block a user