add first run notice

This commit is contained in:
geekgeekrun
2024-04-15 02:32:38 +08:00
parent 822e67a185
commit 24576fa2c0
5 changed files with 242 additions and 3 deletions

View File

@@ -0,0 +1,14 @@
import fs from 'fs'
import os from 'os'
import path from 'path'
import buildInfo from '../../common/build-info.json'
export const firstLaunchNoticeApproveFlagPath = path.join(
os.homedir(),
'.geekgeekrun/storage',
'ui-first-launch-notice-flag'
)
export const isFirstLaunchNoticeApproveFlagExist = () => fs.existsSync(firstLaunchNoticeApproveFlagPath)
export const createFirstLaunchNoticeApproveFlag = () =>
fs.writeFileSync(firstLaunchNoticeApproveFlagPath, buildInfo.version)

View File

@@ -0,0 +1,49 @@
import { BrowserWindow, ipcMain } from 'electron'
import path from 'path'
import { createFirstLaunchNoticeApproveFlag } from '../features/first-launch-notice-window'
export let firstLaunchNoticeWindow: BrowserWindow | null = null
export function createFirstLaunchNoticeWindow(
opt?: Electron.BrowserWindowConstructorOptions
): BrowserWindow {
// Create the browser window.
firstLaunchNoticeWindow = new BrowserWindow({
width: 720,
height: 640,
resizable: false,
show: false,
webPreferences: {
preload: path.join(__dirname, '../preload/index.js'),
sandbox: false
},
...opt
})
firstLaunchNoticeWindow.on('ready-to-show', () => {
firstLaunchNoticeWindow!.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']) {
firstLaunchNoticeWindow.loadURL(process.env['ELECTRON_RENDERER_URL'] + '#/first-run-readme')
} else {
firstLaunchNoticeWindow.loadFile(
path.join(__dirname, '../renderer/index.html') + '#/first-run-readme'
)
}
firstLaunchNoticeWindow!.once('closed', () => {
firstLaunchNoticeWindow = null
})
return firstLaunchNoticeWindow!
}
export const initIpc = () => {
ipcMain.handle('first-launch-notice-approve', () => {
createFirstLaunchNoticeApproveFlag()
firstLaunchNoticeWindow?.close()
})
}
initIpc()

View File

@@ -1,13 +1,15 @@
import { BrowserWindow, shell } from 'electron'
import path from 'path'
import { openDevTools } from '../commands'
import { createFirstLaunchNoticeWindow } from './firstLaunchNoticeWindow'
import { isFirstLaunchNoticeApproveFlagExist } from '../features/first-launch-notice-window'
export let mainWindow: BrowserWindow | null = null
export function createMainWindow(): void {
export function createMainWindow(): BrowserWindow {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 1024,
height: 640,
height: 720,
show: false,
autoHideMenuBar: true,
...(process.platform === 'linux'
@@ -26,6 +28,14 @@ export function createMainWindow(): void {
mainWindow.on('ready-to-show', () => {
mainWindow.show()
})
mainWindow.on('ready-to-show', async () => {
!isFirstLaunchNoticeApproveFlagExist() &&
createFirstLaunchNoticeWindow({
parent: mainWindow!,
modal: true,
show: true
})
})
mainWindow.webContents.setWindowOpenHandler((details) => {
shell.openExternal(details.url)
@@ -43,4 +53,5 @@ export function createMainWindow(): void {
mainWindow!.once('closed', () => {
mainWindow = null
})
return mainWindow!
}

View File

@@ -0,0 +1,158 @@
<template>
<div class="first-run-readme">
<div class="first-run-readme__inner">
<div class="readme-title">欢迎使用GeekGeekRun祝您求职顺利~</div>
<div class="readme-desc">
如下是使用必读请您逐条阅读如果已经了解且接受请在每一条前面打勾
</div>
<article class="readme-article">
<ElCheckboxGroup
v-model="readmeItemCheckStatusList"
@change="handleReadmeItemCheckStatusListChange"
>
<ElCheckbox :label="0" :class="[unreadItemsAfterClickSubmit[0] ? 'unread' : '']">
本程序从某种程度上说属于辅助工具是与<el-link
@click="
electron.ipcRenderer.send(
'open-external-link',
'https://about.zhipin.com/agreement/'
)
"
>Boss直聘用户协议</el-link
>
相关条款相违背的
根据该条款如果一些非正常用户行为被风控监测到您需要承受包括不仅限于<b
class="color-red"
>账号被强制退出登录</b
><b class="color-red">账号被限制使用</b><b class="color-red">账号被封禁</b
>等对您不利的风险因此使用本程序即意味着<b class="color-red">您愿意接受以上风险</b
>且如果相关风险发生<b class="color-red">您需要自行承担相关后果</b><b
class="color-red"
>本程序不负责</b
>
</ElCheckbox>
<ElCheckbox :label="1" :class="[unreadItemsAfterClickSubmit[1] ? 'unread' : '']">
本程序会通过尽可能模仿用户行为来规避相关风险但并不能保证可以完全规避建议您使用本程序时<b
class="color-red"
>注意节制</b
>建议当天开聊次数用尽后隔几天再使用建议您<b class="color-red"
>注册一个本程序专用的新的Boss直聘账号</b
>进行求职
</ElCheckbox>
<ElCheckbox :label="2" :class="[unreadItemsAfterClickSubmit[2] ? 'unread' : '']">
本程序原理是模拟用户在Boss直聘网页上进行点击操作Boss网站每过一段时间会发生改版这可能会导致本程序相关脚本失效此时您可以点击程序左下角进行反馈
</ElCheckbox>
<ElCheckbox :label="3" :class="[unreadItemsAfterClickSubmit[3] ? 'unread' : '']">
本程序需要存储您的登录凭据即Cookie来模拟您在Boss直聘上开聊Boss的行为本程序仅会把您的Cookie存储在本地并在您访问Boss直聘时将其传输到Boss直聘<b
class="color-red"
>不会泄露给第三方</b
>也不会进行除自动开聊Boss以外的行为<b class="color-red">请勿向他人泄漏您的Cookie</b
>
</ElCheckbox>
<ElCheckbox :label="4" :class="[unreadItemsAfterClickSubmit[4] ? 'unread' : '']">
本程序不包含任何用于统计用户行为上报程序错误的组件<b class="color-red"
>不会上报您的隐私诸如求职期望开聊记录等也不会向您的雇主报告您的求职行为</b
>如果您在使用过程中遇上程序错误您可以点击程序左下角进行反馈
</ElCheckbox>
<ElCheckbox :label="5" :class="[unreadItemsAfterClickSubmit[5] ? 'unread' : '']">
<b class="color-red">本程序不对您的求职过程与结果负责</b
>为您开聊的职位均在由Boss直聘为您推送的推荐职位中出现过<b class="color-red"
>自行甄别为您开聊的公司认真决定是否参加面试慎重选择Offer</b
>
</ElCheckbox>
<ElCheckbox :label="6" :class="[unreadItemsAfterClickSubmit[6] ? 'unread' : '']">
请在Boss直聘上<b class="color-red">屏蔽您不期望投递的公司</b>
</ElCheckbox>
</ElCheckboxGroup>
</article>
<footer flex mt20px pb20px flex-justify-end>
<el-button type="text" @click="handleCancel">退出程序</el-button>
<el-button type="primary" @click="handleSubmit"
>我已经阅读并接受上方所提及的相关风险</el-button
>
</footer>
</div>
</div>
</template>
<script lang="ts" setup>
import { ElCheckbox, ElCheckboxGroup, ElMessage } from 'element-plus'
import { ref } from 'vue'
const electron = window.electron
const readmeItemCheckStatusList = ref<number[]>([])
const handleCancel = () => {
electron.ipcRenderer.invoke('exit-app-immediately')
}
const unreadItemsAfterClickSubmit = ref<Record<number, true>>({})
const handleSubmit = () => {
const COUNT = 7
if (readmeItemCheckStatusList.value.length !== COUNT) {
ElMessage.warning(
`您还有${COUNT - readmeItemCheckStatusList.value.length}条没有读完,读完就打勾标记一下吧`
)
unreadItemsAfterClickSubmit.value = {}
for (let i = 0; i < COUNT; i++) {
if (!readmeItemCheckStatusList.value.includes(i)) {
unreadItemsAfterClickSubmit.value[i] = true
}
}
return
}
electron.ipcRenderer.invoke('first-launch-notice-approve')
}
const handleReadmeItemCheckStatusListChange = (value: number[]) => {
value.forEach((it) => {
if (unreadItemsAfterClickSubmit.value[it]) {
delete unreadItemsAfterClickSubmit.value[it]
}
})
}
</script>
<style lang="scss" scoped>
.first-run-readme {
max-width: 640px;
margin: 0 auto;
height: 100vh;
box-sizing: border-box;
&__inner {
padding-top: 30px;
.readme-title {
}
.readme-desc {
margin-top: 10px;
}
.readme-article {
margin-top: 10px;
:deep(.el-checkbox) {
height: fit-content;
align-items: flex-start;
margin-right: 0;
padding-left: 8px;
border-left: 4px solid transparent;
&.unread {
border-left-color: #f77a36;
background-color: #fff5df;
}
.el-checkbox__input {
margin-top: 3px;
}
.el-checkbox__label {
line-height: 1.5em;
white-space: normal;
}
& + .el-checkbox {
margin-top: 8px;
}
&.is-checked .el-checkbox__label {
color: unset;
opacity: 0.6;
}
}
}
}
}
</style>

View File

@@ -2,6 +2,13 @@ import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
import BootstrapSplash from '@renderer/page/BootstrapSplash/index.vue'
const routes: Array<RouteRecordRaw> = [
{
path: '/first-run-readme',
component: () => import('@renderer/page/FirstRunReadme/index.vue'),
meta: {
title: '初次使用必读'
}
},
{
path: '/cookieAssistant',
component: () => import('@renderer/page/CookieAssistant/index.vue'),
@@ -65,7 +72,7 @@ const routes: Array<RouteRecordRaw> = [
},
}
]
},
}
]
const router = createRouter({