diff --git a/README.md b/README.md index f2a72dc..095f216 100644 --- a/README.md +++ b/README.md @@ -166,3 +166,11 @@ Boss不明原因已读不回?简历就是投不出去? 更多功能还在开发中~ 祝你求职成功,事业顺利,事事顺心 + +## Star 数据 感谢支持 + + + + + Star History Chart + diff --git a/packages/geek-auto-start-chat-with-boss/default-config-file/boss.json b/packages/geek-auto-start-chat-with-boss/default-config-file/boss.json index c724ced..678ca57 100644 --- a/packages/geek-auto-start-chat-with-boss/default-config-file/boss.json +++ b/packages/geek-auto-start-chat-with-boss/default-config-file/boss.json @@ -16,6 +16,7 @@ "geminiApiKey": "", "rechatContentSource": 1, "recentMessageQuantityForLlm": 8, - "rechatLlmFallback": 1 + "rechatLlmFallback": 1, + "onlyRemindBossWithExpectJobType": true } } \ No newline at end of file diff --git a/packages/geek-auto-start-chat-with-boss/default-config-file/target-company-list.json b/packages/geek-auto-start-chat-with-boss/default-config-file/target-company-list.json index 1fdf70e..09c0944 100644 --- a/packages/geek-auto-start-chat-with-boss/default-config-file/target-company-list.json +++ b/packages/geek-auto-start-chat-with-boss/default-config-file/target-company-list.json @@ -1,4 +1,4 @@ [ "青钱","软通动力","南天","睿服","中电金信","佰钧成","云链","博彦","汉克时代","柯莱特","拓保","亿达信息","纬创","微创","微澜","诚迈科技","法本","兆尹","诚迈","联合永道","新致软件","宇信科技","华为","德科","FESCO","科锐","科之锐", - "抖音","字节","字跳","有竹居","脸萌","头条","懂车帝","滴滴","嘀嘀","巨量引擎","小桔","网易","有道","腾讯","酷狗","酷我","阅文","搜狗","京东","沃东天骏","达达","达冠","百度","昆仑芯","小度","度小满","爱奇艺","携程","趣拿","去哪儿","集度","智图","长地万方","瑞图万方","道道通","小熊博望","理想","蔚来","顺丰","讯飞","同程","艺龙","马蜂窝","贝壳","自如","链家","我爱我家","相寓","多点","金山","小米","猎豹","新浪","微博","阿里","淘宝","淘麦郎","天猫","盒马","口碑","优视","夸克","UC","蚂蚁","高德","LAZADA","来赞达","飞猪","菜鸟","哈啰","钉钉","乌鸫","饿了么","美团","三快","猫眼","快手","映客","小红书","行吟","奇虎","360","三六零","鸿盈","奇富","奇元","亚信","启明星辰","奇安信","深信服","长亭","绿盟","天融信","商汤","SenseTime","大华","海康威视","hikvision","汽车之家","车好多","瓜子","易车","昆仑万维","昆仑天工","闲徕","趣加","FunPlus","完美","马上消费","轻松","水滴","白龙马","58","车欢欢","五八","红布林","致美","快狗","天鹅到家","转转","美餐","知乎","智者四海","易点云","搜狐","用友","畅捷通","猿辅导","小猿","猿力","好未来","学而思","希望学","新东方","东方甄选","东方优选","作业帮","高途","跟谁学","学科网","天学网","一起教育","一起作业","美术宝","火花思维","粉笔","老虎国际","一心向上","向上一意","联想","拉勾","乐视","欢聚","竞技世界","拼多多","寻梦","得物","Moka","希瑞亚斯","北森","OPPO","欧珀","vivo","维沃","小天才","步步高","读书郎","货拉拉","陌陌","探探","Shopee","首汽租车","GoFun","神州租车","天眼查","旷视","小冰","美图","智谱华章","MiniMax","石头科技","迅雷","TP","希音","SHEIN","稀宇","深言","百川智能","与爱为舞","牵手","Grab","爱回收","洋钱罐","瓴岳","得到","思维造物","地平线","咪咕","翼支付","电信","天翼","联通","蓝湖","墨刀" + "抖音","字节","字跳","有竹居","脸萌","头条","懂车帝","滴滴","嘀嘀","巨量引擎","小桔","网易","有道","腾讯","酷狗","酷我","阅文","搜狗","小鹅通","富途","京东","沃东天骏","达达","达冠","百度","昆仑芯","小度","度小满","爱奇艺","携程","趣拿","去哪儿","集度","智图","长地万方","瑞图万方","道道通","小熊博望","理想","蔚来","顺丰","丰巢","中通","圆通","申通","跨越","讯飞","同程","艺龙","马蜂窝","贝壳","自如","链家","我爱我家","相寓","多点","金山","小米","猎豹","新浪","微博","阿里","淘宝","淘麦郎","天猫","盒马","口碑","优视","夸克","UC","蚂蚁","高德","LAZADA","来赞达","飞猪","菜鸟","哈啰","钉钉","乌鸫","饿了么","美团","三快","猫眼","快手","映客","小红书","行吟","奇虎","360","三六零","鸿盈","奇富","奇元","亚信","启明星辰","奇安信","深信服","长亭","绿盟","天融信","商汤","SenseTime","大华","海康威视","hikvision","汽车之家","车好多","瓜子","易车","昆仑万维","昆仑天工","闲徕","趣加","FunPlus","完美","马上消费","轻松","水滴","白龙马","58","车欢欢","五八","红布林","致美","快狗","天鹅到家","转转","美餐","知乎","智者四海","易点云","搜狐","用友","畅捷通","猿辅导","小猿","猿力","好未来","学而思","希望学","新东方","东方甄选","东方优选","作业帮","高途","跟谁学","学科网","天学网","一起教育","一起作业","美术宝","火花思维","粉笔","51talk","爱学习","高思","老虎国际","一心向上","向上一意","联想","拉勾","乐视","欢聚","竞技世界","拼多多","寻梦","从鲸","TEMU","得物","有赞","Moka","希瑞亚斯","北森","OPPO","欧珀","vivo","维沃","小天才","步步高","读书郎","货拉拉","陌陌","探探","Shopee","虾皮","首汽租车","GoFun","神州租车","天眼查","旷视","小冰","美图","智谱华章","MiniMax","石头科技","迅雷","TP","锐捷","Tenda","腾达","斐讯","希音","SHEIN","稀宇","深言","百川智能","与爱为舞","牵手","Grab","爱回收","洋钱罐","瓴岳","得到","思维造物","地平线","咪咕","翼支付","电信","天翼","联通","蓝湖","墨刀","海尔","美的","米哈游","传音","同花顺","国美","TCL" ] \ No newline at end of file diff --git a/packages/sqlite-plugin/package.json b/packages/sqlite-plugin/package.json index 46b9798..d61ad33 100644 --- a/packages/sqlite-plugin/package.json +++ b/packages/sqlite-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@geekgeekrun/sqlite-plugin", - "version": "0.0.1", + "version": "0.0.2", "description": "", "main": "dist/index.js", "dependencies": { diff --git a/packages/sqlite-plugin/src/index.ts b/packages/sqlite-plugin/src/index.ts index f9bf251..2940b04 100644 --- a/packages/sqlite-plugin/src/index.ts +++ b/packages/sqlite-plugin/src/index.ts @@ -1,6 +1,7 @@ import "reflect-metadata"; import { type DataSource } from "typeorm"; import { requireTypeorm } from "./utils/module-loader"; +import fs from 'node:fs' import { BossInfo } from "./entity/BossInfo"; import { BossInfoChangeLog } from "./entity/BossInfoChangeLog"; @@ -28,12 +29,13 @@ import minimist from 'minimist' import { UpdateBossInfoTable1732032381304 } from "./migrations/1732032381304-UpdateBossInfoTable"; import { MarkAsNotSuitOp, MarkAsNotSuitReason } from "./enums"; import { AddColumnForMarkAsNotSuitLog1746092370665 } from "./migrations/1746092370665-AddColumnForMarkAsNotSuitLog"; +import { Init1000000000000 } from "./migrations/1000000000000-Init"; export function initDb(dbFilePath) { const { DataSource } = requireTypeorm() const appDataSource = new DataSource({ type: "sqlite", - synchronize: true, + synchronize: false, logging: true, logger: "simple-console", database: dbFilePath, @@ -59,6 +61,7 @@ export function initDb(dbFilePath) { LlmModelUsageRecord, ], migrations: [ + Init1000000000000, UpdateChatStartupLogTable1729182577167, UpdateBossInfoTable1732032381304, AddColumnForMarkAsNotSuitLog1746092370665, diff --git a/packages/sqlite-plugin/src/migrations/1000000000000-Init.ts b/packages/sqlite-plugin/src/migrations/1000000000000-Init.ts new file mode 100644 index 0000000..bc323d6 --- /dev/null +++ b/packages/sqlite-plugin/src/migrations/1000000000000-Init.ts @@ -0,0 +1,24 @@ +import { DataSource, MigrationInterface, QueryRunner, TableColumn } from "typeorm"; +export class Init1000000000000 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + const tableSchemaStatements = `CREATE TABLE IF NOT EXISTS "boss_info" ("encryptBossId" varchar PRIMARY KEY NOT NULL, "encryptCompanyId" varchar, "name" varchar NOT NULL, "date" datetime NOT NULL, "title" varchar NOT NULL); +CREATE TABLE IF NOT EXISTS "boss_info_change_log" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "encryptBossId" varchar NOT NULL, "updateTime" datetime NOT NULL, "dataAsJson" varchar NOT NULL); +CREATE TABLE IF NOT EXISTS "chat_startup_log" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "encryptJobId" varchar NOT NULL, "encryptCurrentUserId" varchar NOT NULL, "date" datetime NOT NULL, "chatStartupFrom" integer, "autoStartupChatRecordId" integer); +CREATE TABLE IF NOT EXISTS "company_info_change_log" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "encryptCompanyId" varchar NOT NULL, "updateTime" datetime NOT NULL, "dataAsJson" varchar NOT NULL); +CREATE TABLE IF NOT EXISTS "company_info" ("encryptCompanyId" varchar PRIMARY KEY NOT NULL, "name" varchar NOT NULL, "brandName" varchar NOT NULL, "scaleLow" integer, "scaleHigh" integer, "stageName" varchar, "industryName" varchar); +CREATE TABLE IF NOT EXISTS "job_info" ("encryptJobId" varchar PRIMARY KEY NOT NULL, "jobName" varchar NOT NULL, "positionName" varchar NOT NULL, "salaryLow" integer, "salaryHigh" integer, "salaryMonth" integer, "experienceName" varchar NOT NULL, "publishDate" datetime, "degreeName" varchar, "address" varchar, "description" varchar NOT NULL, "encryptBossId" varchar NOT NULL, "encryptCompanyId" varchar NOT NULL); +CREATE TABLE IF NOT EXISTS "job_info_change_log" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "encryptJobId" varchar NOT NULL, "updateTime" datetime NOT NULL, "dataAsJson" varchar NOT NULL); +CREATE TABLE IF NOT EXISTS "boss_active_status_record" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "encryptBossId" varchar NOT NULL, "lastActiveStatus" varchar, "updateTime" datetime NOT NULL); +CREATE TABLE IF NOT EXISTS "user_info" ("encryptUserId" varchar PRIMARY KEY NOT NULL, "name" varchar NOT NULL); +CREATE TABLE IF NOT EXISTS "auto_start_chat_run_record" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "date" datetime NOT NULL); +CREATE TABLE IF NOT EXISTS "mark_as_not_suit_log" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "encryptJobId" varchar NOT NULL, "encryptCurrentUserId" varchar NOT NULL, "date" datetime NOT NULL, "markFrom" integer, "markReason" integer, "extInfo" varchar, "autoStartupChatRecordId" integer); +CREATE TABLE IF NOT EXISTS "chat_message_record" ("mid" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "encryptFromUserId" varchar NOT NULL, "encryptToUserId" varchar NOT NULL, "time" datetime, "type" varchar, "style" varchar, "text" varchar, "imageUrl" varchar, "imageWidth" integer, "imageHeight" integer); +CREATE TABLE IF NOT EXISTS "llm_model_usage_record" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "providerCompleteApiUrl" varchar NOT NULL, "model" varchar NOT NULL, "providerApiSecret" varchar, "completionTokens" integer, "promptTokens" integer, "promptCacheHitTokens" integer, "promptCacheMissTokens" integer, "totalTokens" integer, "requestStartTime" datetime NOT NULL, "requestEndTime" datetime, "hasError" boolean NOT NULL, "errorMessage" varchar NOT NULL, "requestScene" integer);`.split('\n') + for(const statement of tableSchemaStatements) { + await queryRunner.query(statement); + } + } + + public async down(queryRunner: QueryRunner): Promise { + } +} diff --git a/packages/sqlite-plugin/src/migrations/1729182577167-UpdateChatStartupLogTable.ts b/packages/sqlite-plugin/src/migrations/1729182577167-UpdateChatStartupLogTable.ts index 9e6e1f4..972a5d4 100644 --- a/packages/sqlite-plugin/src/migrations/1729182577167-UpdateChatStartupLogTable.ts +++ b/packages/sqlite-plugin/src/migrations/1729182577167-UpdateChatStartupLogTable.ts @@ -1,19 +1,24 @@ -import { MigrationInterface, QueryRunner, TableColumn } from "typeorm"; +import { DataSource, MigrationInterface, QueryRunner, TableColumn } from "typeorm"; +import { VBossLibrary } from "../entity/VBossLibrary"; +import { VChatStartupLog } from "../entity/VChatStartupLog"; +import { VCompanyLibrary } from "../entity/VCompanyLibrary"; +import { VJobLibrary } from "../entity/VJobLibrary"; +import { VMarkAsNotSuitLog } from "../entity/VMarkAsNotSuitLog"; -const viewNames = [ - "v_boss_library", - "v_chat_startup_log", - "v_company_library", - "v_job_library", - "v_mark_as_not_suit_log" -]; +const ViewEntities = [ + VBossLibrary, + VChatStartupLog, + VCompanyLibrary, + VJobLibrary, + VMarkAsNotSuitLog, +] -export class UpdateChatStartupLogTable1729182577167 - implements MigrationInterface -{ +export class UpdateChatStartupLogTable1729182577167 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { - for (const viewName of viewNames) { - await queryRunner.query(`DROP VIEW IF EXISTS "${viewName}"`); + for (const EntityDefinition of ViewEntities) { + const dataSource = queryRunner.connection as DataSource; + const viewMetadata = dataSource.getMetadata(EntityDefinition); + await queryRunner.query(`DROP VIEW IF EXISTS "${viewMetadata.tableName}"`); } if (await queryRunner.hasTable("boss_active_status_record")) { if (await queryRunner.hasColumn("boss_active_status_record", "updateDate")) { @@ -40,14 +45,17 @@ export class UpdateChatStartupLogTable1729182577167 }) ) } + for (const EntityDefinition of ViewEntities) { + const dataSource = queryRunner.connection as DataSource; + const viewMetadata = dataSource.getMetadata(EntityDefinition); + let expression = viewMetadata.expression; + if (typeof expression === 'function') { + expression = expression(dataSource).getQuery(); + } + await queryRunner.query(`CREATE VIEW "${viewMetadata.tableName}" AS ${expression}`); + } } public async down(queryRunner: QueryRunner): Promise { - for (const viewName of viewNames) { - await queryRunner.query(`DROP VIEW IF EXISTS "${viewName}"`); - } - await queryRunner.query( - `ALTER TABLE boss_active_status_record RENAME COLUMN updateTime TO updateDate` - ); } } diff --git a/packages/sqlite-plugin/src/migrations/1732032381304-UpdateBossInfoTable.ts b/packages/sqlite-plugin/src/migrations/1732032381304-UpdateBossInfoTable.ts index 1a3a979..1f56a98 100644 --- a/packages/sqlite-plugin/src/migrations/1732032381304-UpdateBossInfoTable.ts +++ b/packages/sqlite-plugin/src/migrations/1732032381304-UpdateBossInfoTable.ts @@ -1,17 +1,24 @@ -import { MigrationInterface, QueryRunner, TableColumn } from "typeorm"; +import { DataSource, MigrationInterface, QueryRunner, TableColumn } from "typeorm"; +import { VBossLibrary } from "../entity/VBossLibrary"; +import { VChatStartupLog } from "../entity/VChatStartupLog"; +import { VCompanyLibrary } from "../entity/VCompanyLibrary"; +import { VJobLibrary } from "../entity/VJobLibrary"; +import { VMarkAsNotSuitLog } from "../entity/VMarkAsNotSuitLog"; -const viewNames = [ - "v_boss_library", - "v_chat_startup_log", - "v_company_library", - "v_job_library", - "v_mark_as_not_suit_log", -]; +const ViewEntities = [ + VBossLibrary, + VChatStartupLog, + VCompanyLibrary, + VJobLibrary, + VMarkAsNotSuitLog, +] export class UpdateBossInfoTable1732032381304 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { - for (const viewName of viewNames) { - await queryRunner.query(`DROP VIEW IF EXISTS "${viewName}"`); + for (const EntityDefinition of ViewEntities) { + const dataSource = queryRunner.connection as DataSource; + const viewMetadata = dataSource.getMetadata(EntityDefinition); + await queryRunner.query(`DROP VIEW IF EXISTS "${viewMetadata.tableName}"`); } if (await queryRunner.hasTable("boss_info")) { if (await queryRunner.hasColumn("boss_info", "encryptCompanyId")) { @@ -26,6 +33,15 @@ export class UpdateBossInfoTable1732032381304 implements MigrationInterface { ); } } + for (const EntityDefinition of ViewEntities) { + const dataSource = queryRunner.connection as DataSource; + const viewMetadata = dataSource.getMetadata(EntityDefinition); + let expression = viewMetadata.expression; + if (typeof expression === 'function') { + expression = expression(dataSource).getQuery(); + } + await queryRunner.query(`CREATE VIEW "${viewMetadata.tableName}" AS ${expression}`); + } } public async down(queryRunner: QueryRunner): Promise {} diff --git a/packages/sqlite-plugin/src/migrations/1746092370665-AddColumnForMarkAsNotSuitLog.ts b/packages/sqlite-plugin/src/migrations/1746092370665-AddColumnForMarkAsNotSuitLog.ts index 536ed7f..db98e30 100644 --- a/packages/sqlite-plugin/src/migrations/1746092370665-AddColumnForMarkAsNotSuitLog.ts +++ b/packages/sqlite-plugin/src/migrations/1746092370665-AddColumnForMarkAsNotSuitLog.ts @@ -1,17 +1,24 @@ -import { MigrationInterface, QueryRunner, TableColumn } from "typeorm"; +import { DataSource, MigrationInterface, QueryRunner, TableColumn } from "typeorm"; +import { VBossLibrary } from "../entity/VBossLibrary"; +import { VChatStartupLog } from "../entity/VChatStartupLog"; +import { VCompanyLibrary } from "../entity/VCompanyLibrary"; +import { VJobLibrary } from "../entity/VJobLibrary"; +import { VMarkAsNotSuitLog } from "../entity/VMarkAsNotSuitLog"; -const viewNames = [ - "v_boss_library", - "v_chat_startup_log", - "v_company_library", - "v_job_library", - "v_mark_as_not_suit_log", -]; +const ViewEntities = [ + VBossLibrary, + VChatStartupLog, + VCompanyLibrary, + VJobLibrary, + VMarkAsNotSuitLog, +] export class AddColumnForMarkAsNotSuitLog1746092370665 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { - for (const viewName of viewNames) { - await queryRunner.query(`DROP VIEW IF EXISTS "${viewName}"`); + for (const EntityDefinition of ViewEntities) { + const dataSource = queryRunner.connection as DataSource; + const viewMetadata = dataSource.getMetadata(EntityDefinition); + await queryRunner.query(`DROP VIEW IF EXISTS "${viewMetadata.tableName}"`); } if (await queryRunner.hasTable("mark_as_not_suit_log")) { if (!await queryRunner.hasColumn("mark_as_not_suit_log", "markOp")) { @@ -25,6 +32,15 @@ export class AddColumnForMarkAsNotSuitLog1746092370665 implements MigrationInter ); } } + for (const EntityDefinition of ViewEntities) { + const dataSource = queryRunner.connection as DataSource; + const viewMetadata = dataSource.getMetadata(EntityDefinition); + let expression = viewMetadata.expression; + if (typeof expression === 'function') { + expression = expression(dataSource).getQuery(); + } + await queryRunner.query(`CREATE VIEW "${viewMetadata.tableName}" AS ${expression}`); + } } public async down(queryRunner: QueryRunner): Promise {} diff --git a/packages/ui/package.json b/packages/ui/package.json index ca4bcfa..f1b50b6 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "geekgeekrun-ui", - "version": "0.4.0", + "version": "0.6.0", "description": "Boss 炸弹 - 自动开聊Boss,助力每位打工人求职!", "main": "./out/main/index.js", "author": "geekgeekrun", @@ -39,6 +39,7 @@ "diff": "^7.0.0", "electron-updater": "^6.1.7", "minimist": "^1.2.8", + "mitt": "^3.0.1", "node-machine-id": "^1.1.12", "pinia": "^3.0.2", "puppeteer": "20.1.0", diff --git a/packages/ui/src/common/build-info.json b/packages/ui/src/common/build-info.json index 74d28d6..7da6b5a 100644 --- a/packages/ui/src/common/build-info.json +++ b/packages/ui/src/common/build-info.json @@ -1,7 +1,7 @@ { - "version": "0.4.0", - "buildVersion": 9, - "buildTime": 1745903517984, - "buildHash": "25e52530228e78c3cf78caa053c7da6bb138e5e2", + "version": "0.6.0", + "buildVersion": 11, + "buildTime": 1746646530387, + "buildHash": "97793adb0f75dd39a5ee4b0768a0d92587046a6c", "name": "geekgeekrun-ui" } \ No newline at end of file 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 b5b799d..6d07658 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 @@ -513,16 +513,15 @@ export default function initIpc() { ipcMain.handle('save-resume-content', saveResumeHandler) resumeEditorWindow?.once('closed', () => { ipcMain.removeHandler('save-resume-content') - ipcMain.removeHandler('fetch-resume-content') defer.reject(new Error('cancel')) }) - ipcMain.handle('fetch-resume-content', async () => { - const res = (await readConfigFile('resumes.json'))?.[0] - return res?.content ?? null - }) return defer.promise }) + ipcMain.handle('fetch-resume-content', async () => { + const res = (await readConfigFile('resumes.json'))?.[0] + return res?.content ?? null + }) ipcMain.on('no-reply-reminder-prompt-edit', async () => { const template = await readStorageFile(autoReminderPromptTemplateFileName, { isJson: false }) if (!template) { diff --git a/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER/index.ts b/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER/index.ts index 0e6f617..0560f55 100644 --- a/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER/index.ts +++ b/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER/index.ts @@ -32,6 +32,10 @@ const rechatLlmFallback = readConfigFile('boss.json').autoReminder?.rechatLlmFallback ?? RECHAT_LLM_FALLBACK.SEND_LOOK_FORWARD_EMOTION +const expectJobTypeRegExpStr = readConfigFile('boss.json').expectJobTypeRegExpStr +const onlyRemindBossWithExpectJobType = + readConfigFile('boss.json').autoReminder?.onlyRemindBossWithExpectJobType ?? !!expectJobTypeRegExpStr + const dbInitPromise = initDb(getPublicDbFilePath()) export const pageMapByName: { @@ -117,7 +121,6 @@ const mainLoop = async () => { '你与该职位竞争者PK情况', '简历诊断提醒', '附件简历还没准备好', - '开场问题,期待你的回答', '设置合适的期望薪资范围' ].map((it) => new RegExp(it)) browser = await bootstrap() @@ -198,9 +201,10 @@ const mainLoop = async () => { (rechatLimitDay && it.updateTime ? +new Date() - it.updateTime < rechatLimitDay * 24 * 60 * 60 * 1000 : true) && - ((it.lastIsSelf && it.lastMsgStatus === MsgStatus.HAS_READ) || + ((((it.lastIsSelf && it.lastMsgStatus === MsgStatus.HAS_READ) || canNotConfirmIfHasReadMsgTemplateList.some((regExp) => regExp.test(it.lastText))) && - !it.unreadCount + !it.unreadCount) || + (!it.lastIsSelf && it.lastText === '开场问题,期待你的回答')) ) }) @@ -267,6 +271,24 @@ const mainLoop = async () => { }) } await sleepWithRandomDelay(1500) + // check if expect job type match + let isExpectJobTypeMatch = true + if (onlyRemindBossWithExpectJobType) { + const selectedFriendInfo = await pageMapByName.boss?.evaluate( + `document.querySelector('.chat-conversation')?.__vue__?.selectedFriend$` + ) + if (!selectedFriendInfo) { + isExpectJobTypeMatch = false + } else { + const jobType = selectedFriendInfo?.positionName + if (!jobType) { + isExpectJobTypeMatch = false + } else { + const regExp = new RegExp(expectJobTypeRegExpStr) + isExpectJobTypeMatch = regExp.test(jobType) + } + } + } const conversationInfo = await pageMapByName.boss?.evaluate( `document.querySelector('.chat-conversation .chat-im.chat-editor')?.__vue__?.conversation$` ) @@ -280,6 +302,7 @@ const mainLoop = async () => { const lastGeekMessageSendTime = historyMessageList.findLast((it) => it.isSelf)?.time ?? 0 if ( + isExpectJobTypeMatch && historyMessageList[historyMessageList.length - 1].isSelf && historyMessageList[historyMessageList.length - 1].status === MsgStatus.HAS_READ && ((conversationInfo && diff --git a/packages/ui/src/renderer/src/page/MainLayout/GeekAutoStartChatWithBoss.vue b/packages/ui/src/renderer/src/page/MainLayout/GeekAutoStartChatWithBoss.vue index c6ad120..819ea12 100644 --- a/packages/ui/src/renderer/src/page/MainLayout/GeekAutoStartChatWithBoss.vue +++ b/packages/ui/src/renderer/src/page/MainLayout/GeekAutoStartChatWithBoss.vue @@ -133,7 +133,7 @@
-
职位类型正则(不区分大小写)
+
职位类型正则(推荐填写,不区分大小写)
+ 发送提醒消息前,先按照“Boss炸弹-职位类型正则”校验正在与Boss沟通的岗位是否满足期望,校验通过后再提醒 + + + +
@@ -184,6 +208,7 @@ import { RECHAT_LLM_FALLBACK } from '../../../../common/enums/auto-start-chat' import { gtagRenderer } from '@renderer/utils/gtag' +import mittBus from '../../utils/mitt' const router = useRouter() const formContent = ref({ @@ -192,7 +217,8 @@ const formContent = ref({ rechatLimitDay: 21, rechatContentSource: 1, recentMessageQuantityForLlm: 8, - rechatLlmFallback: RECHAT_LLM_FALLBACK.SEND_LOOK_FORWARD_EMOTION + rechatLlmFallback: RECHAT_LLM_FALLBACK.SEND_LOOK_FORWARD_EMOTION, + onlyRemindBossWithExpectJobType: true } }) @@ -224,10 +250,32 @@ electron.ipcRenderer.invoke('fetch-config-file-content').then((res) => { ? 8 : parseInt(conf.recentMessageQuantityForLlm) : 8 + conf.onlyRemindBossWithExpectJobType = conf.onlyRemindBossWithExpectJobType ?? true conf.rechatLlmFallback = conf.rechatLlmFallback ?? RECHAT_LLM_FALLBACK.SEND_LOOK_FORWARD_EMOTION formContent.value.autoReminder = conf }) +const expectJobTypeRegExpStr = ref('') +async function fetchExpectJobTypeRegExpStr() { + await electron.ipcRenderer.invoke('fetch-config-file-content').then((res) => { + expectJobTypeRegExpStr.value = res.config['boss.json']?.expectJobTypeRegExpStr + }) +} +fetchExpectJobTypeRegExpStr() +mittBus.on('auto-start-chat-with-boss-config-saved', fetchExpectJobTypeRegExpStr) +onUnmounted(() => { + mittBus.off('auto-start-chat-with-boss-config-saved', fetchExpectJobTypeRegExpStr) +}) + +const resumeContent = ref(null) +async function fetchResumeContent() { + await electron.ipcRenderer.invoke('fetch-resume-content').then((res) => { + resumeContent.value = res + }) +} + +fetchResumeContent() + const formRules = { throttleIntervalMinutes: { validator(_, value, cb) { @@ -274,6 +322,7 @@ async function checkIsCanRun() { gtagRenderer('invalid_rc_dialog_click_confirm') try { await electron.ipcRenderer.invoke('resume-edit') + await fetchResumeContent() } catch (err) { console.log(err) } @@ -449,6 +498,7 @@ const handleClickEditResume = async () => { gtagRenderer('edit_resume_clicked') try { await electron.ipcRenderer.invoke('resume-edit') + await fetchResumeContent() } catch (err) { console.log(err) } diff --git a/packages/ui/src/renderer/src/utils/mitt.ts b/packages/ui/src/renderer/src/utils/mitt.ts new file mode 100644 index 0000000..b61b745 --- /dev/null +++ b/packages/ui/src/renderer/src/utils/mitt.ts @@ -0,0 +1,3 @@ +import mitt from 'mitt' +const mittBus = mitt() +export default mittBus diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 74067c4..4402ddd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -132,6 +132,9 @@ importers: minimist: specifier: ^1.2.8 version: 1.2.8 + mitt: + specifier: ^3.0.1 + version: 3.0.1 node-machine-id: specifier: ^1.1.12 version: 1.1.12