自动化操作实战——自动登录、自动填表单、自动点击
能做哪些自动化
PakePlus 的 JS 注入能力 + 桌面 APP 形态,特别适合做那些"每天重复几次、手动操作繁琐"的事情:
| 自动化场景 | 说明 |
|---|---|
| 自动登录 | 打开 APP 后自动填入账号密码、点登录 |
| 自动填表单 | 固定表单的常用字段自动填入 |
| 自动点击 | 定时点击某个按钮(比如打卡、签到、刷新) |
| 自动跳转 | 打开 APP 后自动跳到指定页面 |
| 自动刷新 | 定时刷新页面(配合 PakePlus 窗口持久化) |
| 定时任务 | 用 setInterval / setTimeout 实现定时执行 |
实战一:自动登录
最简单的版本
假设打包了一个公司内部 OA 系统,每次打开都要输入账号密码:
// auto-login.js
// 等登录表单出现后自动填入并提交
const doLogin = () => {
const usernameInput = document.querySelector('input[name="username"]');
const passwordInput = document.querySelector('input[name="password"]');
const loginButton = document.querySelector('button[type="submit"], button.login-btn');
if (usernameInput && passwordInput && loginButton) {
usernameInput.value = 'your-username';
passwordInput.value = 'your-password';
// 触发 React/Vue 的状态更新(有些框架要这样写)
usernameInput.dispatchEvent(new Event('input', { bubbles: true }));
passwordInput.dispatchEvent(new Event('input', { bubbles: true }));
loginButton.click();
return true; // 表示登录表单已找到并处理
}
return false; // 登录表单还没出现
};
// 立即尝试一次
if (!doLogin()) {
// 如果没找到登录表单,持续监听直到它出现
const observer = new MutationObserver(() => {
if (doLogin()) observer.disconnect();
});
observer.observe(document.body, { childList: true, subtree: true });
}
更安全的版本:localStorage 存凭据
把账号密码硬编码在 JS 里不安全——APP 打包后别人打开就能看到。建议用 localStorage 存,并加一层加密(简单 base64 不算真正加密,但至少不是明文):
// auto-login-safe.js
const getCredentials = () => {
try {
const encoded = localStorage.getItem('pakeplus_creds');
if (!encoded) return null;
const decoded = atob(encoded);
return JSON.parse(decoded);
} catch {
return null;
}
};
const doLogin = () => {
const creds = getCredentials();
if (!creds) {
console.warn('没有找到登录凭据,请先手动登录一次,脚本会自动记住');
return false;
}
// ... 填入 creds.username / creds.password 并提交
};
手动登录一次后,JS 可以自动把凭据存进 localStorage:
// 登录成功后自动保存凭据(在你自己的扩展脚本里)
const username = document.querySelector('input[name="username"]').value;
const password = document.querySelector('input[name="password"]').value;
const encoded = btoa(JSON.stringify({ username, password }));
localStorage.setItem('pakeplus_creds', encoded);
实战二:定时刷新
假设打包了一个数据看板,需要每分钟自动刷新一次:
// auto-refresh.js
const REFRESH_INTERVAL = 60 * 1000; // 60 秒
// 方式一:整页刷新
setInterval(() => {
window.location.reload();
}, REFRESH_INTERVAL);
// 方式二:只刷新数据(如果是 SPA,整页刷新会重置状态)
// 这种方式需要根据目标网站的 API 写,伪代码如下:
// setInterval(async () => {
// const resp = await fetch('/api/dashboard');
// const data = await resp.json();
// renderDashboard(data); // 自己写渲染逻辑
// }, REFRESH_INTERVAL);
实战三:自动点击打卡按钮
假设打包了一个每日签到/打卡网站,每天打开 APP 自动点:
// auto-checkin.js
const clickCheckin = () => {
// 等待打卡按钮出现
const button = document.querySelector('.checkin-btn, [class*="sign"], button.check-in');
if (button && !button.disabled) {
button.click();
console.log('已自动点击打卡按钮');
}
};
// 启动后等 3 秒(页面完全加载好)再尝试
setTimeout(clickCheckin, 3000);
// 如果需要在特定日期跳过(比如周末),可以加条件:
// const today = new Date();
// if (today.getDay() !== 0 && today.getDay() !== 6) clickCheckin();
实战四:自动跳转
假设打开 APP 后默认是首页,但你想直接跳转到"我的工作台":
// auto-navigate.js
// 等路由系统就绪后跳转
const tryNavigate = () => {
// 方式一:直接改 location(简单粗暴,适合同域 SPA)
if (location.pathname === '/' || location.pathname === '/home') {
location.href = '/dashboard';
return true;
}
// 方式二:如果是 React Router,可以用 history.push
if (window.ReactRouter?.history) {
window.ReactRouter.history.push('/dashboard');
return true;
}
return false;
};
if (!tryNavigate()) {
// 持续尝试 10 秒
const timer = setInterval(() => {
if (tryNavigate() || Date.now() - window.pakeplusStartTime > 10000) {
clearInterval(timer);
}
}, 500);
}
实战五:自动填表单的特定字段
假设打包了一个发票申请系统,每次都要填相同的抬头信息:
// auto-fill-form.js
const presetData = {
'input[name="company"]': '某某科技有限公司',
'input[name="taxId"]': '91300000XXXXXXXXXX',
'select[name="invoiceType"]': '增值税专用发票',
};
const fillPresetFields = () => {
for (const [selector, value] of Object.entries(presetData)) {
const el = document.querySelector(selector);
if (!el || el.value) continue; // 已填过的跳过
el.value = value;
// 触发 React/Vue 状态更新
el.dispatchEvent(new Event('input', { bubbles: true }));
el.dispatchEvent(new Event('change', { bubbles: true }));
}
};
// 表单出现就填
const observer = new MutationObserver(() => fillPresetFields());
observer.observe(document.body, { childList: true, subtree: true });
fillPresetFields();
React/Vue 框架的特殊处理
如果目标网站是 React 或 Vue 应用,element.value = xxx 可能不会触发 UI 更新——这些框架用虚拟 DOM,直接改 value 不会同步到内部状态。
React 的解决
const input = document.querySelector('input');
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
nativeInputValueSetter.call(input, 'new value');
input.dispatchEvent(new Event('input', { bubbles: true }));
Vue 的解决
const input = document.querySelector('input');
const proto = Object.getPrototypeOf(input);
const setter = Object.getOwnPropertyDescriptor(proto, 'value').set;
setter.call(input, 'new value');
input.dispatchEvent(new Event('input', { bubbles: true }));
安全边界
自动化脚本能做的事情强大,但要注意:
| 注意事项 | 说明 |
|---|---|
| 登录凭据安全 | 不要硬编码密码,用 localStorage 存(见上面的安全版本) |
不要滥用 executeCommand | 这个 API 能执行任意系统命令,自动化脚本里用它等于在用户电脑上留后门 |
| 目标网站的服务条款 | 有些网站禁止自动化操作(违反 robots.txt 或 ToS) |
| 不要打包带敏感凭据的产物 | 密码写在 JS 里打包出来 = 所有人都能看 |