mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-09-07 00:17:17 +08:00
visualize prerequisite check steps
This commit is contained in:
@@ -149,10 +149,10 @@ function handleMessage(socket, message) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case 'worker-message': {
|
case 'worker-to-gui-message': {
|
||||||
// 转发工具进程消息到GUI客户端
|
// 转发工具进程消息到GUI客户端
|
||||||
broadcastToGUI({
|
broadcastToGUI({
|
||||||
type: 'worker-message',
|
type: 'worker-to-gui-message',
|
||||||
workerId: workerId,
|
workerId: workerId,
|
||||||
data: message.data || message,
|
data: message.data || message,
|
||||||
timestamp: Date.now()
|
timestamp: Date.now()
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
export const getAutoStartChatSteps = () => [{
|
||||||
|
id: 'worker-launch',
|
||||||
|
describe: '启动子进程',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// id: 'basic-cookie-check',
|
||||||
|
// describe: 'Cookie 格式检查',
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
id: 'puppeteer-executable-check',
|
||||||
|
describe: 'Puppeteer 可执行程序检查',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'login-status-check',
|
||||||
|
describe: '登录状态检查',
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { sendToDaemon } from "../flow/OPEN_SETTING_WINDOW/connect-to-daemon"
|
||||||
|
import minimist from 'minimist'
|
||||||
|
|
||||||
|
const runRecordId = minimist(process.argv.slice(2))['run-record-id'] ?? null
|
||||||
|
export function pushUserInfoValidStatus (userInfoResponse) {
|
||||||
|
sendToDaemon({
|
||||||
|
type: 'worker-to-gui-message',
|
||||||
|
data: {
|
||||||
|
type: 'prerequisite-step-by-step-checkstep-by-step-check',
|
||||||
|
step: {
|
||||||
|
id: 'login-status-check',
|
||||||
|
status: userInfoResponse.code === 0 ? 'fulfilled' : 'rejected'
|
||||||
|
},
|
||||||
|
runRecordId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UserResponseInfoPlugin {
|
||||||
|
apply(hooks) {
|
||||||
|
hooks.userInfoResponse.tapPromise(
|
||||||
|
"UserResponseInfoPlugin",
|
||||||
|
(userInfoResponse) => {
|
||||||
|
pushUserInfoValidStatus(userInfoResponse)
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,33 +3,37 @@ import { sendToDaemon } from "../flow/OPEN_SETTING_WINDOW/connect-to-daemon"
|
|||||||
import { saveAndGetCurrentRunRecord } from "../flow/OPEN_SETTING_WINDOW/utils/db"
|
import { saveAndGetCurrentRunRecord } from "../flow/OPEN_SETTING_WINDOW/utils/db"
|
||||||
|
|
||||||
export async function runCommon ({ mode }) {
|
export async function runCommon ({ mode }) {
|
||||||
const currentRunRecord = (await saveAndGetCurrentRunRecord())?.data
|
const currentRunRecord = (await saveAndGetCurrentRunRecord())?.data
|
||||||
const subProcessEnv = {
|
const subProcessEnv = {
|
||||||
...process.env,
|
...process.env,
|
||||||
GEEKGEEKRUND_NO_AUTO_RESTART_EXIT_CODE: [
|
GEEKGEEKRUND_NO_AUTO_RESTART_EXIT_CODE: [
|
||||||
AUTO_CHAT_ERROR_EXIT_CODE.PUPPETEER_IS_NOT_EXECUTABLE,
|
AUTO_CHAT_ERROR_EXIT_CODE.PUPPETEER_IS_NOT_EXECUTABLE,
|
||||||
AUTO_CHAT_ERROR_EXIT_CODE.LOGIN_STATUS_INVALID,
|
AUTO_CHAT_ERROR_EXIT_CODE.LOGIN_STATUS_INVALID,
|
||||||
AUTO_CHAT_ERROR_EXIT_CODE.LLM_UNAVAILABLE
|
AUTO_CHAT_ERROR_EXIT_CODE.LLM_UNAVAILABLE
|
||||||
].join(',')
|
].join(',')
|
||||||
|
}
|
||||||
|
const args = process.env.NODE_ENV === 'development' ? [
|
||||||
|
process.argv[1],
|
||||||
|
`--mode=${mode}`,
|
||||||
|
`--run-record-id=${currentRunRecord?.id || 0}`
|
||||||
|
] : [
|
||||||
|
`--mode=${mode}`,
|
||||||
|
`--run-record-id=${currentRunRecord?.id || 0}`
|
||||||
|
]
|
||||||
|
await sendToDaemon(
|
||||||
|
{
|
||||||
|
type: 'start-worker',
|
||||||
|
workerId: mode,
|
||||||
|
command: process.argv[0],
|
||||||
|
args,
|
||||||
|
env: subProcessEnv
|
||||||
|
},
|
||||||
|
{
|
||||||
|
needCallback: true
|
||||||
}
|
}
|
||||||
const args = process.env.NODE_ENV === 'development' ? [
|
)
|
||||||
process.argv[1],
|
|
||||||
`--mode=${mode}`,
|
return {
|
||||||
`--run-record-id=${currentRunRecord?.id || 0}`
|
runRecordId: currentRunRecord?.id
|
||||||
] : [
|
}
|
||||||
`--mode=${mode}`,
|
|
||||||
`--run-record-id=${currentRunRecord?.id || 0}`
|
|
||||||
]
|
|
||||||
await sendToDaemon(
|
|
||||||
{
|
|
||||||
type: 'start-worker',
|
|
||||||
workerId: mode,
|
|
||||||
command: process.argv[0],
|
|
||||||
args,
|
|
||||||
env: subProcessEnv
|
|
||||||
},
|
|
||||||
{
|
|
||||||
needCallback: true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
@@ -10,13 +10,14 @@ import { getAnyAvailablePuppeteerExecutable } from '../CHECK_AND_DOWNLOAD_DEPEND
|
|||||||
import { sleep } from '@geekgeekrun/utils/sleep.mjs'
|
import { sleep } from '@geekgeekrun/utils/sleep.mjs'
|
||||||
import { AUTO_CHAT_ERROR_EXIT_CODE } from '../../../common/enums/auto-start-chat'
|
import { AUTO_CHAT_ERROR_EXIT_CODE } from '../../../common/enums/auto-start-chat'
|
||||||
import attachListenerForKillSelfOnParentExited from '../../utils/attachListenerForKillSelfOnParentExited'
|
import attachListenerForKillSelfOnParentExited from '../../utils/attachListenerForKillSelfOnParentExited'
|
||||||
|
import minimist from 'minimist'
|
||||||
import SqlitePluginModule from '@geekgeekrun/sqlite-plugin'
|
import SqlitePluginModule from '@geekgeekrun/sqlite-plugin'
|
||||||
import gtag from '../../utils/gtag'
|
import gtag from '../../utils/gtag'
|
||||||
import GtagPlugin from '../../utils/gtag/GtagPlugin'
|
import GtagPlugin from '../../utils/gtag/GtagPlugin'
|
||||||
import { connectToDaemon, sendToDaemon } from '../OPEN_SETTING_WINDOW/connect-to-daemon'
|
import { connectToDaemon, sendToDaemon } from '../OPEN_SETTING_WINDOW/connect-to-daemon'
|
||||||
import { PeriodPushCurrentPageScreenshotPlugin } from '../../utils/screenshot'
|
import { PeriodPushCurrentPageScreenshotPlugin } from '../../utils/screenshot'
|
||||||
import { checkShouldExit } from '../../utils/worker'
|
import { checkShouldExit } from '../../utils/worker'
|
||||||
|
import { UserResponseInfoPlugin } from '../../features/boss-user-info-response-plugin'
|
||||||
const { default: SqlitePlugin } = SqlitePluginModule
|
const { default: SqlitePlugin } = SqlitePluginModule
|
||||||
|
|
||||||
const rerunInterval = (() => {
|
const rerunInterval = (() => {
|
||||||
@@ -35,15 +36,39 @@ const initPlugins = (hooks) => {
|
|||||||
new SqlitePlugin(getPublicDbFilePath()).apply(hooks)
|
new SqlitePlugin(getPublicDbFilePath()).apply(hooks)
|
||||||
new GtagPlugin().apply(hooks)
|
new GtagPlugin().apply(hooks)
|
||||||
new PeriodPushCurrentPageScreenshotPlugin().apply(hooks)
|
new PeriodPushCurrentPageScreenshotPlugin().apply(hooks)
|
||||||
|
new UserResponseInfoPlugin().apply(hooks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const runRecordId = minimist(process.argv.slice(2))['run-record-id'] ?? null
|
||||||
const runAutoChat = async () => {
|
const runAutoChat = async () => {
|
||||||
app.dock?.hide()
|
app.dock?.hide()
|
||||||
const puppeteerExecutable = await getAnyAvailablePuppeteerExecutable()
|
const puppeteerExecutable = await getAnyAvailablePuppeteerExecutable()
|
||||||
if (!puppeteerExecutable) {
|
if (!puppeteerExecutable) {
|
||||||
|
sendToDaemon({
|
||||||
|
type: 'worker-to-gui-message',
|
||||||
|
data: {
|
||||||
|
type: 'prerequisite-step-by-step-checkstep-by-step-check',
|
||||||
|
step: {
|
||||||
|
id: 'puppeteer-executable-check',
|
||||||
|
status: 'rejected'
|
||||||
|
},
|
||||||
|
runRecordId
|
||||||
|
}
|
||||||
|
})
|
||||||
app.exit(AUTO_CHAT_ERROR_EXIT_CODE.PUPPETEER_IS_NOT_EXECUTABLE)
|
app.exit(AUTO_CHAT_ERROR_EXIT_CODE.PUPPETEER_IS_NOT_EXECUTABLE)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
sendToDaemon({
|
||||||
|
type: 'worker-to-gui-message',
|
||||||
|
data: {
|
||||||
|
type: 'prerequisite-step-by-step-checkstep-by-step-check',
|
||||||
|
step: {
|
||||||
|
id: 'puppeteer-executable-check',
|
||||||
|
status: 'fulfilled'
|
||||||
|
},
|
||||||
|
runRecordId
|
||||||
|
}
|
||||||
|
})
|
||||||
process.env.PUPPETEER_EXECUTABLE_PATH = puppeteerExecutable.executablePath
|
process.env.PUPPETEER_EXECUTABLE_PATH = puppeteerExecutable.executablePath
|
||||||
const { initPuppeteer, mainLoop, closeBrowserWindow, autoStartChatEventBus } = await import(
|
const { initPuppeteer, mainLoop, closeBrowserWindow, autoStartChatEventBus } = await import(
|
||||||
'@geekgeekrun/geek-auto-start-chat-with-boss/index.mjs'
|
'@geekgeekrun/geek-auto-start-chat-with-boss/index.mjs'
|
||||||
@@ -131,6 +156,17 @@ export const waitForProcessHandShakeAndRunAutoChat = async () => {
|
|||||||
needCallback: true
|
needCallback: true
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
sendToDaemon({
|
||||||
|
type: 'worker-to-gui-message',
|
||||||
|
data: {
|
||||||
|
type: 'prerequisite-step-by-step-checkstep-by-step-check',
|
||||||
|
step: {
|
||||||
|
id: 'worker-launch',
|
||||||
|
status: 'fulfilled'
|
||||||
|
},
|
||||||
|
runRecordId
|
||||||
|
}
|
||||||
|
})
|
||||||
runAutoChat()
|
runAutoChat()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ export default function initIpc() {
|
|||||||
|
|
||||||
ipcMain.handle('run-geek-auto-start-chat-with-boss', async (ev) => {
|
ipcMain.handle('run-geek-auto-start-chat-with-boss', async (ev) => {
|
||||||
const mode = 'geekAutoStartWithBossMain'
|
const mode = 'geekAutoStartWithBossMain'
|
||||||
await runCommon({ mode })
|
const { runRecordId } = await runCommon({ mode })
|
||||||
daemonEE.on('message', function handler (message) {
|
daemonEE.on('message', function handler (message) {
|
||||||
if (message.workerId !== mode) {
|
if (message.workerId !== mode) {
|
||||||
return
|
return
|
||||||
@@ -226,11 +226,12 @@ export default function initIpc() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
return { runRecordId }
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.handle('run-read-no-reply-auto-reminder', async () => {
|
ipcMain.handle('run-read-no-reply-auto-reminder', async () => {
|
||||||
const mode = 'readNoReplyAutoReminderMain'
|
const mode = 'readNoReplyAutoReminderMain'
|
||||||
await runCommon({ mode })
|
const { runRecordId } = await runCommon({ mode })
|
||||||
daemonEE.on('message', function handler (message) {
|
daemonEE.on('message', function handler (message) {
|
||||||
if (message.workerId !== mode) {
|
if (message.workerId !== mode) {
|
||||||
return
|
return
|
||||||
@@ -254,6 +255,7 @@ export default function initIpc() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
return { runRecordId }
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.handle('check-dependencies', async () => {
|
ipcMain.handle('check-dependencies', async () => {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import { connectToDaemon, sendToDaemon } from '../OPEN_SETTING_WINDOW/connect-to
|
|||||||
import { pushCurrentPageScreenshot, SCREENSHOT_INTERVAL_MS } from '../../utils/screenshot'
|
import { pushCurrentPageScreenshot, SCREENSHOT_INTERVAL_MS } from '../../utils/screenshot'
|
||||||
import { checkShouldExit } from '../../utils/worker'
|
import { checkShouldExit } from '../../utils/worker'
|
||||||
import { getAnyAvailablePuppeteerExecutable } from '../CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable'
|
import { getAnyAvailablePuppeteerExecutable } from '../CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable'
|
||||||
|
import minimist from 'minimist'
|
||||||
|
|
||||||
const throttleIntervalMinutes =
|
const throttleIntervalMinutes =
|
||||||
readConfigFile('boss.json').autoReminder?.throttleIntervalMinutes ?? 10
|
readConfigFile('boss.json').autoReminder?.throttleIntervalMinutes ?? 10
|
||||||
@@ -249,12 +250,34 @@ const mainLoop = async () => {
|
|||||||
// #region
|
// #region
|
||||||
if (currentPageUrl.startsWith('https://www.zhipin.com/web/user/')) {
|
if (currentPageUrl.startsWith('https://www.zhipin.com/web/user/')) {
|
||||||
writeStorageFile('boss-cookies.json', [])
|
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')
|
throw new Error('LOGIN_STATUS_INVALID')
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
currentPageUrl.startsWith('https://www.zhipin.com/web/common/403.html') ||
|
currentPageUrl.startsWith('https://www.zhipin.com/web/common/403.html') ||
|
||||||
currentPageUrl.startsWith('https://www.zhipin.com/web/common/error.html')
|
currentPageUrl.startsWith('https://www.zhipin.com/web/common/error.html')
|
||||||
) {
|
) {
|
||||||
|
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('ACCESS_IS_DENIED')
|
throw new Error('ACCESS_IS_DENIED')
|
||||||
}
|
}
|
||||||
if (currentPageUrl.startsWith('https://www.zhipin.com/web/user/safe/verify-slider')) {
|
if (currentPageUrl.startsWith('https://www.zhipin.com/web/user/safe/verify-slider')) {
|
||||||
@@ -277,9 +300,31 @@ const mainLoop = async () => {
|
|||||||
})
|
})
|
||||||
if (validateRes.code === 0) {
|
if (validateRes.code === 0) {
|
||||||
await storeStorage(pageMapByName.boss)
|
await storeStorage(pageMapByName.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
|
||||||
|
}
|
||||||
|
})
|
||||||
throw new Error('CAPTCHA_PASSED_AND_NEED_RESTART')
|
throw new Error('CAPTCHA_PASSED_AND_NEED_RESTART')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sendToDaemon({
|
||||||
|
type: 'worker-to-gui-message',
|
||||||
|
data: {
|
||||||
|
type: 'prerequisite-step-by-step-checkstep-by-step-check',
|
||||||
|
step: {
|
||||||
|
id: 'login-status-check',
|
||||||
|
status: 'fulfilled'
|
||||||
|
},
|
||||||
|
runRecordId
|
||||||
|
}
|
||||||
|
})
|
||||||
// #endregion
|
// #endregion
|
||||||
// check set security question tip modal
|
// check set security question tip modal
|
||||||
let setSecurityQuestionTipModelProxy = await pageMapByName.boss!.$(
|
let setSecurityQuestionTipModelProxy = await pageMapByName.boss!.$(
|
||||||
@@ -478,19 +523,53 @@ const rerunInterval = (() => {
|
|||||||
return v
|
return v
|
||||||
})()
|
})()
|
||||||
|
|
||||||
|
const runRecordId = minimist(process.argv.slice(2))['run-record-id'] ?? null
|
||||||
export async function runEntry() {
|
export async function runEntry() {
|
||||||
app.dock?.hide()
|
app.dock?.hide()
|
||||||
const puppeteerExecutable = await getAnyAvailablePuppeteerExecutable()
|
|
||||||
if (!puppeteerExecutable) {
|
|
||||||
throw new Error(`PUPPETEER_IS_NOT_EXECUTABLE`)
|
|
||||||
}
|
|
||||||
process.env.PUPPETEER_EXECUTABLE_PATH = puppeteerExecutable.executablePath
|
|
||||||
await connectToDaemon()
|
await connectToDaemon()
|
||||||
await sendToDaemon({
|
await sendToDaemon({
|
||||||
type: 'ping'
|
type: 'ping'
|
||||||
}, {
|
}, {
|
||||||
needCallback: true
|
needCallback: true
|
||||||
})
|
})
|
||||||
|
sendToDaemon({
|
||||||
|
type: 'worker-to-gui-message',
|
||||||
|
data: {
|
||||||
|
type: 'prerequisite-step-by-step-checkstep-by-step-check',
|
||||||
|
step: {
|
||||||
|
id: 'worker-launch',
|
||||||
|
status: 'fulfilled'
|
||||||
|
},
|
||||||
|
runRecordId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const puppeteerExecutable = await getAnyAvailablePuppeteerExecutable()
|
||||||
|
if (!puppeteerExecutable) {
|
||||||
|
sendToDaemon({
|
||||||
|
type: 'worker-to-gui-message',
|
||||||
|
data: {
|
||||||
|
type: 'prerequisite-step-by-step-checkstep-by-step-check',
|
||||||
|
step: {
|
||||||
|
id: 'puppeteer-executable-check',
|
||||||
|
status: 'rejected'
|
||||||
|
},
|
||||||
|
runRecordId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
throw new Error(`PUPPETEER_IS_NOT_EXECUTABLE`)
|
||||||
|
}
|
||||||
|
sendToDaemon({
|
||||||
|
type: 'worker-to-gui-message',
|
||||||
|
data: {
|
||||||
|
type: 'prerequisite-step-by-step-checkstep-by-step-check',
|
||||||
|
step: {
|
||||||
|
id: 'puppeteer-executable-check',
|
||||||
|
status: 'fulfilled'
|
||||||
|
},
|
||||||
|
runRecordId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
process.env.PUPPETEER_EXECUTABLE_PATH = puppeteerExecutable.executablePath
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
await mainLoop()
|
await mainLoop()
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import path from 'path'
|
|||||||
import { openDevTools } from '../commands'
|
import { openDevTools } from '../commands'
|
||||||
import { createFirstLaunchNoticeWindow } from './firstLaunchNoticeWindow'
|
import { createFirstLaunchNoticeWindow } from './firstLaunchNoticeWindow'
|
||||||
import { isFirstLaunchNoticeApproveFlagExist } from '../features/first-launch-notice-window'
|
import { isFirstLaunchNoticeApproveFlagExist } from '../features/first-launch-notice-window'
|
||||||
|
import { daemonEE } from '../flow/OPEN_SETTING_WINDOW/connect-to-daemon'
|
||||||
export let mainWindow: BrowserWindow | null = null
|
export let mainWindow: BrowserWindow | null = null
|
||||||
|
|
||||||
export function createMainWindow(): BrowserWindow {
|
export function createMainWindow(): BrowserWindow {
|
||||||
@@ -58,5 +59,10 @@ export function createMainWindow(): BrowserWindow {
|
|||||||
mainWindow!.once('closed', () => {
|
mainWindow!.once('closed', () => {
|
||||||
mainWindow = null
|
mainWindow = null
|
||||||
})
|
})
|
||||||
|
daemonEE.on('message', (message) => {
|
||||||
|
if (message.type === 'worker-to-gui-message') {
|
||||||
|
mainWindow?.webContents?.send('worker-to-gui-message', message)
|
||||||
|
}
|
||||||
|
})
|
||||||
return mainWindow!
|
return mainWindow!
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,22 @@
|
|||||||
:close-on-press-escape="false"
|
:close-on-press-escape="false"
|
||||||
:show-close="false"
|
:show-close="false"
|
||||||
>
|
>
|
||||||
|
<!-- v-if="stepsForRender.some(it => ['todo', 'pending', 'rejected'].includes(it.status))" -->
|
||||||
|
<div>
|
||||||
|
<ul m0 pl0>
|
||||||
|
<li list-style-none v-for="item in stepsForRender" flex justify-start pt4px pb4px>
|
||||||
|
<div>
|
||||||
|
<span v-if="item.status === 'todo'">🕐</span>
|
||||||
|
<span v-if="item.status === 'pending'">👉</span>
|
||||||
|
<span v-if="item.status === 'fulfilled'">✅</span>
|
||||||
|
<span v-if="item.status === 'rejected'">⛔️</span>
|
||||||
|
</div>
|
||||||
|
<span ml8px>{{ item.describe }}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
<div flex justify-between items-center w-full>
|
<div flex justify-between items-center w-full>
|
||||||
<div>任务运行中!</div>
|
<div>任务运行中</div>
|
||||||
<div>
|
<div>
|
||||||
<slot name="op-buttons" />
|
<slot name="op-buttons" />
|
||||||
</div>
|
</div>
|
||||||
@@ -17,20 +31,68 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useTaskManagerStore } from '@renderer/store'
|
import { useTaskManagerStore } from '@renderer/store'
|
||||||
import { computed } from 'vue'
|
import { getAutoStartChatSteps } from '../../../../common/prerequisite-step-by-step-check'
|
||||||
|
import { computed, onUnmounted, ref, watch } from 'vue'
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
workerId: {
|
workerId: {
|
||||||
type: String
|
type: String
|
||||||
|
},
|
||||||
|
runRecordId: {
|
||||||
|
type: Number
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const taskManagerStore = useTaskManagerStore()
|
const taskManagerStore = useTaskManagerStore()
|
||||||
const runingTaskInfo = computed(() => {
|
const runingTaskInfo = computed(() => {
|
||||||
return taskManagerStore.runningTasks?.find(it => {
|
return taskManagerStore.runningTasks?.find(it => {
|
||||||
return it.workerId === props.workerId
|
return it.workerId === props.workerId
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
const steps = ref([])
|
||||||
|
const stepsForRender = computed(() => {
|
||||||
|
const clonedSteps = JSON.parse(
|
||||||
|
JSON.stringify(steps.value)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (clonedSteps.some(it => it.status === 'rejected')) {
|
||||||
|
return clonedSteps
|
||||||
|
}
|
||||||
|
const lastFulfilledIndex = clonedSteps.findLastIndex(it => it.status === 'fulfilled')
|
||||||
|
if (lastFulfilledIndex + 1 < clonedSteps.length) {
|
||||||
|
clonedSteps[lastFulfilledIndex + 1].status = 'pending'
|
||||||
|
}
|
||||||
|
return clonedSteps
|
||||||
|
})
|
||||||
|
function fillEmptySteps () {
|
||||||
|
const arr = getAutoStartChatSteps()
|
||||||
|
arr.forEach(it => it.status = 'todo')
|
||||||
|
steps.value = arr
|
||||||
|
}
|
||||||
|
watch(
|
||||||
|
() => props.runRecordId,
|
||||||
|
fillEmptySteps,
|
||||||
|
{
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const { ipcRenderer } = electron
|
||||||
|
|
||||||
|
function messageHandler (ev, { data }) {
|
||||||
|
if (
|
||||||
|
data.type !== 'prerequisite-step-by-step-checkstep-by-step-check' ||
|
||||||
|
data.runRecordId !== props.runRecordId
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const { id: stepId, status: stepStatus } = data.step
|
||||||
|
const targetStep = steps.value.find(it => it.id === stepId)
|
||||||
|
if (!targetStep) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
targetStep.status = stepStatus
|
||||||
|
}
|
||||||
|
const unListenMessage = ipcRenderer.on('worker-to-gui-message', messageHandler)
|
||||||
|
onUnmounted(unListenMessage)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -1062,7 +1062,7 @@
|
|||||||
pointerEvents: 'none'
|
pointerEvents: 'none'
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<RuningOverlay worker-id="geekAutoStartWithBossMain">
|
<RuningOverlay worker-id="geekAutoStartWithBossMain" :run-record-id="runRecordId">
|
||||||
<template #op-buttons>
|
<template #op-buttons>
|
||||||
<el-button @click="handleStopButtonClick">结束任务</el-button>
|
<el-button @click="handleStopButtonClick">结束任务</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -1431,6 +1431,7 @@ const formRules = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const formRef = ref<InstanceType<typeof ElForm>>()
|
const formRef = ref<InstanceType<typeof ElForm>>()
|
||||||
|
const runRecordId = ref(null)
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
gtagRenderer('save_config_and_launch_clicked', {
|
gtagRenderer('save_config_and_launch_clicked', {
|
||||||
has_dingtalk_robot_token: !!formContent.value?.dingtalkRobotAccessToken,
|
has_dingtalk_robot_token: !!formContent.value?.dingtalkRobotAccessToken,
|
||||||
@@ -1469,7 +1470,8 @@ const handleSubmit = async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await electron.ipcRenderer.invoke('run-geek-auto-start-chat-with-boss')
|
const { runRecordId: rrId } = await electron.ipcRenderer.invoke('run-geek-auto-start-chat-with-boss')
|
||||||
|
runRecordId.value = rrId
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof Error && err.message.includes('NEED_TO_CHECK_RUNTIME_DEPENDENCIES')) {
|
if (err instanceof Error && err.message.includes('NEED_TO_CHECK_RUNTIME_DEPENDENCIES')) {
|
||||||
gtagRenderer('gascwb_cannot_run_for_corrupt')
|
gtagRenderer('gascwb_cannot_run_for_corrupt')
|
||||||
|
|||||||
@@ -228,7 +228,7 @@
|
|||||||
pointerEvents: 'none'
|
pointerEvents: 'none'
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<RuningOverlay worker-id="readNoReplyAutoReminderMain">
|
<RuningOverlay worker-id="readNoReplyAutoReminderMain" :run-record-id="runRecordId">
|
||||||
<template #op-buttons>
|
<template #op-buttons>
|
||||||
<el-button @click="handleStopButtonClick">结束任务</el-button>
|
<el-button @click="handleStopButtonClick">结束任务</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -449,7 +449,7 @@ async function checkIsCanRun() {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
const runRecordId = ref(null)
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
gtagRenderer('run_read_no_reply_reminder_clicked', {
|
gtagRenderer('run_read_no_reply_reminder_clicked', {
|
||||||
throttle_interval_minutes: formContent.value.autoReminder.throttleIntervalMinutes,
|
throttle_interval_minutes: formContent.value.autoReminder.throttleIntervalMinutes,
|
||||||
@@ -488,7 +488,8 @@ const handleSubmit = async () => {
|
|||||||
gtagRenderer('run_read_no_reply_reminder_launched')
|
gtagRenderer('run_read_no_reply_reminder_launched')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await electron.ipcRenderer.invoke('run-read-no-reply-auto-reminder')
|
const { runRecordId: rrId } = await electron.ipcRenderer.invoke('run-read-no-reply-auto-reminder')
|
||||||
|
runRecordId.value = rrId
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof Error && err.message.includes('NEED_TO_CHECK_RUNTIME_DEPENDENCIES')) {
|
if (err instanceof Error && err.message.includes('NEED_TO_CHECK_RUNTIME_DEPENDENCIES')) {
|
||||||
gtagRenderer('rnrr_cannot_run_for_corrupt')
|
gtagRenderer('rnrr_cannot_run_for_corrupt')
|
||||||
|
|||||||
Reference in New Issue
Block a user