// 企业微信自动打卡 - 自动解锁版
// 锁屏密码: 521241
auto.waitFor();
auto.setMode("fast");
// ==================== 配置区 ====================
var PIN = "521241"; // 锁屏密码
var MORNING_START = 8; // 上班打卡开始
var MORNING_END = 9; // 上班打卡结束
var EVENING_START = 17; // 下班打卡开始
var EVENING_END = 19; // 下班打卡结束
// ===============================================
var now = new Date();
var hour = now.getHours();
var minute = now.getMinutes();
// 时间段判断
var mode = "";
if (hour >= MORNING_START && hour < MORNING_END) {
mode = "morning";
} else if (hour >= EVENING_START && hour < EVENING_END) {
mode = "evening";
} else {
toast("不在打卡时段");
exit();
}
// 随机延迟 0-180 秒
var delay = Math.floor(Math.random() * 180);
console.log("随机延迟 " + delay + " 秒");
sleep(delay * 1000);
// ==================== 解锁手机 ====================
console.log("开始解锁...");
// 唤醒屏幕
device.wakeUpIfNeeded();
sleep(800);
// 上滑显示密码输入界面
var w = device.width;
var h = device.height;
swipe(w / 2, h * 0.8, w / 2, h * 0.3, 300);
sleep(1000);
// PIN 密码键盘坐标计算
// 标准 Android 密码键盘: 3列 x 4行
// 列: 左=17%, 中=50%, 右=83%
// 行: row1=40%, row2=55%, row3=70%, row4=85%
function getPinPos(num) {
var col, row;
if (num == 0) { col = 1; row = 3; }
else if (num <= 3) { col = num - 1; row = 0; }
else if (num <= 6) { col = num - 4; row = 1; }
else if (num <= 9) { col = num - 7; row = 2; }
var x = w * (0.17 + col * 0.33);
var y = h * (0.40 + row * 0.15);
return [x, y];
}
// 输入密码
var pins = PIN.split("");
for (var i = 0; i < pins.length; i++) {
var num = parseInt(pins[i]);
var pos = getPinPos(num);
click(pos[0], pos[1]);
sleep(200);
}
console.log("密码输入完成");
sleep(1500);
// ==================== 打开企业微信 ====================
app.launchApp("企业微信");
console.log("打开企业微信");
sleep(5000);
// ==================== 进入工作台 ====================
var workTab = text("工作台").findOne(5000);
if (workTab) {
workTab.parent().click();
} else {
click(w / 2, h * 0.88);
}
sleep(3000);
// ==================== 找到打卡 ====================
swipe(w / 2, h * 0.6, w / 2, h * 0.3, 300);
sleep(2000);
var daka = text("打卡").findOne(5000);
if (daka) {
daka.parent().click();
} else {
toast("未找到打卡入口");
exit();
}
sleep(4000);
// ==================== 打卡 ====================
if (mode == "morning") {
var btn = text("上班打卡").findOne(5000);
if (btn) {
btn.parent().click();
toast("✅ 上班打卡 " + hour + ":" + minute);
}
} else {
var btn = text("下班打卡").findOne(5000);
if (btn) {
btn.parent().click();
toast("✅ 下班打卡 " + hour + ":" + minute);
}
}
sleep(3000);
home();
console.log("完成");
回答
你的脚本整体思路可行,但存在几个关键问题,可能导致运行失败或重复打卡。下面逐一说明并给出优化方案。
1. 脚本被重复执行(严重)
脚本末尾又完整复制了一遍前半部分代码,导致实际会执行两次打卡:第一次完毕后,会再次进入时间判断→延迟→解锁→打卡。
必须删除从第二个 // 企业微信自动打卡 - 自动解锁版 开始到结尾的所有重复内容。
2. app.launchApp 参数错误
app.launchApp("企业微信") 应使用包名而非应用显示名称。企业微信的包名是 com.tencent.wework。
改为:
app.launchApp("com.tencent.wework");
3. 解锁流程不够健壮
device.wakeUpIfNeeded()仅点亮屏幕,如果设备已亮屏但处于锁屏界面,你的上滑解锁动作可能失效。- 上滑解锁的坐标
swipe(w/2, h*0.8, w/2, h*0.3, 300)假设锁屏界面就是上滑进入密码,但不同系统/主题可能不同(如需要先上滑再输入密码,或直接显示密码键盘)。 - 密码键盘坐标基于固定百分比,不同分辨率和 DPI 的设备上数字位置可能偏移,导致点击错误密码,多次失败后可能锁死。
建议:
- 使用 Hamibot 的解锁插件或官方
unlock()函数(若有),避免手动计算坐标。 - 如果必须手动输入,应增加前置判断:检测当前是否在锁屏密码输入界面,例如通过寻找“重新输入”或“PIN”等文本,或使用
className("android.widget.TextView").text("0")等控件定位键盘,但最可靠的方式仍是使用插件。
4. 界面元素查找可能不稳定
text("工作台").findOne(5000)和text("打卡").findOne(5000)依赖界面文本,企业微信改版后可能变化。- 坐标点击
click(w/2, h*0.88)作为兜底,也容易点错。 - 建议使用控件 ID 或 desc 定位,可先用
auto.layoutHierarchy()或悬停分析工具获取属性。
5. 代码兼容性
你使用的语法(普通函数、无箭头函数、无默认参数)均兼容 Hamibot 的 Rhino 引擎,无需修改。
6. 建议的优化结构
- 将解锁、打开企业微信、进入打卡等步骤封装成函数,提高可读性。
- 增加异常处理,如解锁失败重试、打卡按钮不存在时重试一次。
- 打卡完成后可加
device.cancelKeepingAwake()恢复屏幕超时,避免耗电。
修改后的核心代码示例(已删除重复,修正包名,添加注释)
// 文档地址 https://docs.hamibot.com/
auto.waitFor();
auto.setMode("fast");
var PIN = "521241";
var MORNING_START = 8, MORNING_END = 9;
var EVENING_START = 17, EVENING_END = 19;
var now = new Date();
var hour = now.getHours();
var minute = now.getMinutes();
var mode = "";
if (hour >= MORNING_START && hour < MORNING_END) {
mode = "morning";
} else if (hour >= EVENING_START && hour < EVENING_END) {
mode = "evening";
} else {
toast("不在打卡时段");
exit();
}
var delay = Math.floor(Math.random() * 180);
console.log("随机延迟 " + delay + " 秒");
sleep(delay * 1000);
// 解锁
console.log("开始解锁...");
device.wakeUpIfNeeded();
sleep(800);
var w = device.width, h = device.height;
swipe(w / 2, h * 0.8, w / 2, h * 0.3, 300);
sleep(1000);
function getPinPos(num) {
var col, row;
if (num == 0) { col = 1; row = 3; }
else if (num <= 3) { col = num - 1; row = 0; }
else if (num <= 6) { col = num - 4; row = 1; }
else if (num <= 9) { col = num - 7; row = 2; }
var x = w * (0.17 + col * 0.33);
var y = h * (0.40 + row * 0.15);
return [x, y];
}
var pins = PIN.split("");
for (var i = 0; i < pins.length; i++) {
var num = parseInt(pins[i]);
var pos = getPinPos(num);
click(pos[0], pos[1]);
sleep(200);
}
console.log("密码输入完成");
sleep(1500);
// 打开企业微信
app.launchApp("com.tencent.wework");
sleep(5000);
// 进入工作台
var workTab = text("工作台").findOne(5000);
if (workTab) {
workTab.parent().click();
} else {
click(w / 2, h * 0.88);
}
sleep(3000);
// 找到打卡
swipe(w / 2, h * 0.6, w / 2, h * 0.3, 300);
sleep(2000);
var daka = text("打卡").findOne(5000);
if (daka) {
daka.parent().click();
} else {
toast("未找到打卡入口");
exit();
}
sleep(4000);
// 执行打卡
if (mode == "morning") {
var btn = text("上班打卡").findOne(5000);
if (btn) btn.parent().click();
} else {
var btn = text("下班打卡").findOne(5000);
if (btn) btn.parent().click();
}
toast("✅ 打卡成功 " + hour + ":" + minute);
sleep(3000);
home();
console.log("完成");
建议下一步
- 在实际设备上测试解锁坐标是否准确,若不准请改用插件。
- 打开企业微信后,可增加
waitForPackage("com.tencent.wework")确保完全启动。 - 如果不想每次手动调试,可使用 Hamibot 的定时任务功能,让脚本在指定时段自动运行。
如果遇到其他具体问题,欢迎继续提问。