我的脚本运行不了, 我也不太清楚报错在那/*
- M3 上下班全流程测试脚本 (黑屏保活版)
- 流程:上班打卡 -> 黑屏等待2分钟 -> 唤醒 -> 下班打卡
- 注意:测试模式下会无视“不在范围”强制点击,仅供测试流程通顺性。
*/
auto.waitFor();
// 检查悬浮窗权限
if (!floaty.checkPermission()) {
toastLog("请先授予悬浮窗权限!");
floaty.requestPermission();
exit();
}
const { myUser, myPass, appName } = hamibot.env;
// 全局变量
var blackWindow = null;
// --- 基础工具 ---
function logInfo(msg) {
log(msg);
toastLog(msg);
}
// 恢复亮度并解锁
function wakeAndRestore() {
logInfo(">>> 正在唤醒设备...");
// 1. 销毁黑屏
if (blackWindow) {
blackWindow.close();
blackWindow = null;
}
// 2. 恢复亮度 (设为自动或最大)
device.setBrightnessMode(0); // 手动模式
device.setBrightness(100); // 恢复亮度
// 3. 唤醒屏幕
device.wakeUp();
sleep(500);
// 4. 索尼 XZ1 上滑解锁
swipe(500, 1600, 500, 200, 300);
sleep(1000);
}
// --- 暴力打卡核心逻辑 ---
function runCheckIn(taskType) {
logInfo("🚀 开始执行 [" + taskType + "]");
var launched = launchApp(appName);
if (!launched) launch("com.seeyon.m3.phone");
sleep(6000); // 等待启动
var maxRetries = 15;
for (var i = 0; i < maxRetries; i++) {
sleep(1000); // 每次循环间隔
// 场景1: 已经在打卡页 (特征: 有“打卡”标题,且有“范围/休息/加载”等字样)
if (text("打卡").exists() && (textContains("范围").exists() || textContains("休息").exists() || textContains("加载").exists())) {
logInfo("📍 锁定打卡页面");
// 暴力测试:即使不在范围也点击
if (textContains("不在范围").exists()) {
logInfo("⚠️ [测试] 忽略不在范围警告,准备强点...");
}
if (textContains("休息").exists()) {
logInfo("⚠️ [测试] 忽略休息日警告,准备强点...");
}
// 点击屏幕中心偏下
var x = device.width / 2;
var y = device.height * 0.55;
click(x, y);
sleep(300);
click(x, y + 150); // 补刀
logInfo("👊 点击动作已执行");
sleep(3000);
captureScreen("/sdcard/test_" + taskType + ".png");
return true;
}
// 场景2: 登录页
else if (text("请登录").exists() || text("登录").exists()) {
logInfo("🔐 需要登录...");
var inputFields = className("EditText").find();
if (inputFields.length >= 2) {
inputFields[0].setText(myUser);
inputFields[1].setText(myPass);
}
var privacy = textContains("已阅读并同意").findOne(2000);
if (privacy) click(privacy.bounds().left - 60, privacy.bounds().centerY());
var loginBtn = text("登录").findOne(2000);
if (loginBtn) { loginBtn.click(); sleep(8000); }
}
// 场景3: 首页/工作台
else if (text("工作台").exists()) {
logInfo("🏠 在首页,前往签到...");
var wb = text("工作台").findOne(2000);
if (wb) click(wb.bounds().centerX(), wb.bounds().centerY());
var si = text("签到").findOne(3000);
if (si) {
// 点击图标
click(si.bounds().centerX(), si.bounds().centerY() - 150);
sleep(3000);
} else {
swipe(500, 1000, 500, 500, 500); // 滑动找找
}
}
// 场景4: 未知/广告
else {
logInfo("❓ 未知页面,后退重试...");
back();
sleep(2000);
}
}
logInfo("❌ 超时未找到打卡入口");
}
// --- 黑屏保活逻辑 ---
function startKeepAlive(minutes) {
logInfo("😴 模拟上班结束,进入黑屏等待 " + minutes + " 分钟...");
logInfo("⚠️ 注意:屏幕将变黑,但脚本仍在运行!请勿手动锁屏!");
sleep(3000);
// 开启全黑悬浮窗
blackWindow = floaty.rawWindow(
<frame gravity="center" bg="#000000">
<vertical>
<text text="测试挂起中..." textColor="#222222" gravity="center" textSize="20sp"/>
<text text="请勿按电源键锁屏" textColor="#222222" gravity="center" marginTop="10"/>
</vertical>
</frame>
);
blackWindow.setSize(-1, -1); // 全屏
blackWindow.setTouchable(true); // 拦截触摸
// 调低亮度
device.setBrightnessMode(0);
device.setBrightness(0);
// 倒计时等待
sleep(minutes * 60 * 1000);
}
// --- 主程序 ---
function main() {
logInfo("🏁 全流程测试开始");
// 1. 模拟上班
wakeAndRestore(); // 确保亮屏
runCheckIn("测试-上班打卡");
// 2. 挂起等待 (测试设为 2 分钟)
startKeepAlive(2);
// 3. 唤醒
wakeAndRestore();
logInfo("⏰ 时间到,自动唤醒!");
// 4. 模拟下班
runCheckIn("测试-下班打卡");
logInfo("✅ 测试结束,请查看相册截图");
hamibot.exit();
}
main();
回答
你的脚本有几个关键问题需要修复,主要是兼容性和配置问题:
1. ES6语法不兼容(最可能的原因)
Hamibot使用Rhino 1.7.15引擎,不支持ES6语法。你的脚本开头有:
const { myUser, myPass, appName } = hamibot.env;
需要修改为:
var myUser = hamibot.env.myUser;
var myPass = hamibot.env.myPass;
var appName = hamibot.env.appName;
2. 黑屏悬浮窗配置错误
你的黑屏悬浮窗文字颜色几乎不可见:
<text text="测试挂起中..." textColor="#222222" .../> // 几乎是黑色文字在黑色背景上
应改为:
<text text="脚本正在运行..." textColor="#FFFFFF" .../> // 白色文字
3. 屏幕截图权限问题
captureScreen()需要屏幕截图权限。在startKeepAlive函数前添加:
if (!requestScreenCapture()) {
toastLog("需要屏幕截图权限");
exit();
}
4. 设备解锁坐标问题
swipe(500, 1600, 500, 200, 300)是硬编码坐标,不同设备会失效。建议使用相对坐标:
var x = device.width / 2;
var startY = device.height * 0.9;
var endY = device.height * 0.2;
swipe(x, startY, x, endY, 300);
5. 启动应用逻辑改进
// 修改前
var launched = launchApp(appName);
if (!launched) launch("com.seeyon.m3.phone");
// 修改后 - 添加错误处理
if (!appName || !launchApp(appName)) {
if (!launch("com.seeyon.m3.phone")) {
toastLog("无法启动M3应用");
exit();
}
}
完整修复建议
-
检查权限:确保已开启无障碍服务、后台弹出界面、屏幕截图权限
-
环境变量配置:在Hamibot控制台为脚本设置环境变量:
myUser: 你的账号myPass: 你的密码appName: "致远M3"(应用商店名称)
-
关键修改代码段:
// 文档地址 https://docs.hamibot.com/
auto.waitFor();
// ES5兼容写法
var myUser = hamibot.env.myUser || "your_username";
var myPass = hamibot.env.myPass || "your_password";
var appName = hamibot.env.appName || "致远M3";
// 确保屏幕截图权限
if (!requestScreenCapture()) {
toastLog("请授予屏幕截图权限");
exit();
}
// 黑屏悬浮窗修正版
function startKeepAlive(minutes) {
logInfo("😴 模拟上班结束,进入黑屏等待 " + minutes + " 分钟...");
blackWindow = floaty.rawWindow(
<frame gravity="center" bg="#000000">
<vertical>
<text text="脚本正在运行..." textColor="#FFFFFF" gravity="center" textSize="20sp"/>
<text text="请勿按电源键锁屏" textColor="#FFFFFF" gravity="center" marginTop="10"/>
</vertical>
</frame>
);
// 修正状态栏问题
let statusBarHeight = context.getResources().getDimensionPixelSize(
context.getResources().getIdentifier('status_bar_height', 'dimen', 'android')
);
blackWindow.setPosition(0, -statusBarHeight);
blackWindow.setSize(-1, -1);
blackWindow.setTouchable(true);
sleep(minutes * 60 * 1000);
}
调试建议
- 先单独测试
wakeAndRestore()函数是否能正常唤醒设备 - 用最简代码测试环境变量:
log("用户名: " + myUser);
log("应用名: " + appName);
toastLog("测试环境变量");
- 如果仍无法运行,先注释掉所有功能代码,逐步启用排查问题
记得每次修改后重启Hamibot服务,因为有些权限变更需要重启才能生效。