自动化脚本
使用 JavaScript 编排鼠标移动、点击、滚动、拖拽、按键、热键和文本输入。适合坐标数组、循环、网格、批量点击以及键鼠组合操作这类用普通步骤不方便表达的自动化。
:::warning 安全提示
本模块会操作真实鼠标和键盘。首次运行相关能力时需要确认桌面控制权限;脚本运行期间,用户操作键盘或鼠标会接管并取消脚本。请先用少量输入测试,不要一开始就对重要数据执行大量点击、按键或文本输入。
:::
应该选择哪个模块
- 只做一次移动、点击或找图定位:使用鼠标输入。
- 执行很短的键盘、鼠标指令串:使用多步骤输入。
- 需要循环、数组、条件判断、坐标计算、热键或键鼠组合操作:使用本模块。
- 需要通用 JavaScript、动作变量读写或可选 CLR:使用运行 Javascript 代码。它与本模块的语法和安全边界不同。
本模块专门提供受控的桌面自动化能力,不是可任意访问系统资源的通用 JavaScript 环境,也不会替换已有的 JavaScript 模块。后续可在同一个 "quicker" 模块中扩展窗口 API,但当前版本尚未导出 window。
当前模块定义
sys:automationScript输入 5 · 输出 4
输入参数
- 脚本内容
scriptText必填要执行的桌面自动化 JavaScript。可使用 export default 导出结果。
查看默认值
import { mouse, key } from "quicker"; mouse.moveTo(100, 200); mouse.click(); key.press("enter"); export default mouse.position(); - 输入
inputAny可选传入脚本的受支持数据。脚本可从 quicker 模块导入 input 读取。
- 超时时间(毫秒)
timeoutMsInteger可选脚本最长运行时间,范围 100 到 120000 毫秒。
- 结束后恢复鼠标位置
restoreMousePositionBoolean可选脚本正常结束或失败时恢复开始前的鼠标位置;用户接管或主动取消时不恢复。
- 失败后停止
stopIfFailBoolean可选失败后是否停止动作
输出参数
- 是否成功
isSuccessBoolean操作是否成功
- 结果
resultAny脚本 export default 导出的受支持值。
- 错误码
errorCodeText稳定的机器可读错误码。
- 错误消息
errMessageText脚本执行失败时的错误消息。
快速开始
在组合动作里添加 自动化脚本,把下面代码填入 脚本内容:
import { mouse } from "quicker";
mouse.moveTo(100, 200);
mouse.click();
export default mouse.position();
脚本会把鼠标移到 (100, 200),单击,然后把最终位置写入步骤的 结果 输出。
自动化脚本
导入方式
"quicker" 是 Quicker 在内存中提供的模块,不是 npm 包或本地文件。当前提供 mouse、key、screen、sleep、input 五个命名导出。
按需导入:
import { mouse, key, screen, sleep, input } from "quicker";
导入整个命名空间:
import * as qk from "quicker";
qk.mouse.click(100, 200);
qk.sleep(200);
也可以使用别名:
import { mouse as m } from "quicker";
m.click(100, 200);
下面两种写法不支持:
import quicker as qk from "quicker"; // 不是 JavaScript 语法
import qk from "quicker"; // quicker 没有 default export
除全局 console 外,这些 API 不会自动变成全局变量;漏写 import 会运行失败。
坐标和点
坐标使用整个 Windows 虚拟桌面的物理像素:主屏左上角通常是 (0, 0),左侧或上方的副屏可能出现负坐标。X 向右增大,Y 向下增大。
一个点可以用三种形式表示:
mouse.click(100, 200);
mouse.click([100, 200]);
mouse.click({ x: 100, y: 200 });
:::caution (x, y) 不是 JavaScript 的坐标类型
const p = (100, 200); // p 的值只有 200
括号里的逗号是 JavaScript 的逗号表达式。需要保存一个点时,请写 [100, 200] 或 { x: 100, y: 200 }。
:::
坐标必须是有限数字,字符串 "100" 不会自动转成数字。输入时允许小数,执行前按 JavaScript Math.round 的规则归一化到整数像素。目标点必须落在某块实际显示器内,不能位于多屏之间的空白区域。
常用示例
循环点击一组坐标
import { mouse, sleep } from "quicker";
const points = [
[320, 240],
[520, 240],
[720, 240]
];
for (const [x, y] of points) {
mouse.click(x, y, { moveDurationMs: 100 });
sleep(200);
}
export default {
count: points.length,
last: mouse.position()
};
使用步骤输入并批量点击
把一个词典或对象绑定到步骤的 输入 参数,例如:
{
"offsetX": 10,
"offsetY": -5,
"points": [[320, 240], [520, 240], [720, 240]]
}
脚本中从 input 读取:
import { mouse, input } from "quicker";
const offsetX = input?.offsetX ?? 0;
const offsetY = input?.offsetY ?? 0;
const points = (input?.points ?? []).map(([x, y]) => [
x + offsetX,
y + offsetY
]);
export default mouse.clickAll(points, {
moveDurationMs: 100,
intervalMs: 200
});
result 将得到 { count, last },其中 last 是最后一次点击后的坐标。
按屏幕比例拖拽
import { mouse, screen } from "quicker";
const start = screen.pointAt(0.25, 0.5);
const end = screen.pointAt(0.75, 0.5);
export default mouse.drag(start, end, {
moveDurationMs: 150,
durationMs: 600
});
screen.pointAt() 默认以主屏为基准。比例 0 到 1 会映射到该屏幕内的有效像素。
在指定位置滚动
import { mouse } from "quicker";
mouse.scroll(-3, {
at: [800, 500],
moveDurationMs: 100
});
正数向上滚,负数向下滚。首版只支持垂直滚轮。
执行热键并输入文本
import { key, sleep } from "quicker";
key.hotkey(["ctrl", "shift"], "s");
sleep(200);
key.type("报告.txt", { intervalMs: 30 });
key.press("enter");
key.press() 操作一个物理按键,key.type() 输入 Unicode 文本。输入中文等文本时使用 key.type(),不要逐个猜测对应的键盘布局。
组合键盘状态和鼠标操作
import { key, mouse } from "quicker";
key.down("shift");
try {
mouse.click(500, 300);
} finally {
key.up("shift");
}
只有确实需要跨多次调用保持按键时才使用 key.down() / key.up()。普通单键和热键优先使用 key.press() / key.hotkey(),更不容易留下未释放的按键状态。
mouse API
除特别说明外,坐标操作成功后都返回最终位置 { x, y }。
| API | 用途 |
|---|---|
mouse.position() | 读取当前鼠标位置。 |
mouse.moveTo(x, y, options?) | 移到绝对坐标。也可把点作为第一个参数。 |
mouse.moveBy(dx, dy, options?) | 从当前位置按像素偏移。 |
mouse.click() | 在当前位置单击逻辑主按钮。 |
mouse.click(options) | 在当前位置按指定按钮单击。 |
mouse.click(x, y, options?) | 移到指定点后单击;点也可写成数组或对象。 |
mouse.doubleClick(...) | 与 click 使用相同的参数形式,执行双击。 |
mouse.clickAll(points, options?) | 依次点击点数组,最多 100 个点;返回 { count, last }。 |
mouse.scroll(verticalClicks, options?) | 垂直滚动 -120..120 click。 |
mouse.dragTo(x, y, options?) | 从当前位置拖到目标点。 |
mouse.drag(from, to, options?) | 先移到起点,再拖到终点。 |
mouse.budget() | 查看本次运行剩余的写操作、按压和滚轮额度。 |
移动选项
{
durationMs: 0 // 0..2000,0 表示直接移动
}
适用于 moveTo 和 moveBy。
点击选项
{
button: "primary", // primary | secondary | middle
moveDurationMs: 0 // 0..2000
}
primary 和 secondary 是 Windows 的逻辑主、次按钮,会遵循系统的左右键交换设置。默认使用 primary。
clickAll 还支持点击间隔:
{
button: "primary",
moveDurationMs: 0,
intervalMs: 200 // 0..10000
}
空点数组不会操作鼠标,返回 { count: 0, last: mouse.position() }。
滚轮选项
{
at: [800, 500], // 可选;省略时在当前位置滚动
moveDurationMs: 0 // 0..2000
}
拖拽选项
// dragTo
{ durationMs: 300 } // 50..2000
// drag
{
moveDurationMs: 0, // 先移动到起点,0..2000
durationMs: 300 // 拖拽过程,50..2000
}
拖拽固定使用逻辑主按钮。首版没有独立的 mouse.down() / mouse.up(),脚本不能跨多次调用保持按钮按下,避免取消或异常后出现“卡键”。
传入未知选项、字符串数字或范围外的整数会返回 INVALID_ARGUMENT。
查询剩余额度
const budget = mouse.budget();
console.log(budget.remainingWrites);
console.log(budget.remainingPresses);
console.log(budget.remainingWheelClicks);
额度由宿主固定,脚本不能提高。任一键鼠输入额度超限后,本次脚本的后续键鼠输入都会被禁用。
key API
| API | 用途 |
|---|---|
key.down(name) | 按下一个支持的物理按键,并由本次脚本持有。 |
key.up(name) | 释放本次脚本已持有的物理按键。 |
key.press(name, options?) | 按下并释放一个物理按键。 |
key.hotkey(modifiers, name, options?) | 依次按下修饰键和主键,再按相反顺序释放。修饰键数组最多 4 项。 |
key.type(text, options?) | 向当前前台窗口输入 Unicode 文本;返回实际处理的字符或换行输入项数。 |
key.budget() | 查看键盘剩余额度和本次脚本当前持有的按键数。 |
按键名称
按键名称不区分大小写,使用一个封闭列表,不接受虚拟键码、扫描码或鼠标伪按键:
- 字母
a..z、主键盘数字0..9 - 功能键
f1..f24、数字键盘numpad0..numpad9 backspace、tab、enter、numpadEnter、pause、escape、spacepageUp、pageDown、end、home、left、up、right、down、insert、deleteshift、ctrl、alt、leftShift、rightShift、leftCtrl、rightCtrl、leftAlt、rightAltleftWin、rightWin、apps、printScreencapsLock、numLock、scrollLocknumpadMultiply、numpadAdd、numpadSubtract、numpadDecimal、numpadDivide
还可以使用这些别名:return 等同于 enter,esc 等同于 escape,control 等同于 ctrl,win 等同于 leftWin,leftControl / rightControl 分别等同于 leftCtrl / rightCtrl。
通用修饰键名 shift、ctrl、alt 分别使用左侧物理按键,与 leftShift、leftCtrl、leftAlt 是同一个按键身份;需要右侧按键时请显式使用 rightShift、rightCtrl、rightAlt。
不在列表里的名称返回 KEY_NOT_SUPPORTED。key.press("A") 与 key.press("a") 都表示物理 A 键;它不会自动按住 Shift 来生成大写文本。需要输入字符时使用 key.type("A")。
按键和热键选项
key.press() 和 key.hotkey() 支持按住时长:
key.press("space", { holdMs: 100 });
key.hotkey(["ctrl", "shift"], "s", { holdMs: 100 });
holdMs 默认为 0,范围 0..2000 毫秒。热键的修饰键不能重复,主键也不能同时出现在修饰键数组中。
输入 Unicode 文本
const count = key.type("你好,Quicker\n第二行", {
intervalMs: 20
});
intervalMs 默认为 0,范围 0..1000 毫秒。\r\n、\r 和 \n 都会作为一次 Enter 输入;其它控制字符和不完整的 Unicode 代理项会被拒绝。文本输入面向普通 Windows 文本控件,不等同于剪贴板粘贴,也不保证游戏、远程桌面或自定义输入控件都接受。
返回值按实际输入项计数:一个 Unicode 代理对(例如一个 emoji)算 1 项,任一种换行序列也算 1 项。键盘文本额度则按原字符串的 UTF-16 代码单元计数,因此一个 emoji 消耗 2 个额度,\r\n 也消耗 2 个额度。
原始按下和释放
key.down() 只能按下本次脚本尚未持有的键;重复按下返回 KEY_ALREADY_HELD。key.up() 只能释放本次脚本持有的键,否则返回 KEY_NOT_HELD。每次脚本最多同时持有 8 个键。
脚本正常结束、取消、超时或失败时,Quicker 都会按相反顺序尝试释放本次脚本仍持有的键。这个兜底不能撤销已经送出的输入,因此仍应使用 try / finally 尽早配对 down() 和 up()。如果脚本正常完成但宿主无法确认清理结果,步骤返回 INPUT_CLEANUP_FAILED;如果脚本已经失败、超时或取消,则保留原结果,并在运行日志中记录清理异常。
查询键盘剩余额度
const budget = key.budget();
console.log(budget.remainingEdges);
console.log(budget.remainingTransactions);
console.log(budget.remainingTextCodeUnits);
console.log(budget.heldKeys);
一次 down 或 up 消耗一个按键边沿;一次 press 消耗两个。额度由宿主固定,脚本不能提高。
screen API
screen 是脚本开始时取得的只读屏幕快照:
import { screen } from "quicker";
console.log(screen.virtualBounds);
console.log(screen.primary);
console.log(screen.displays);
| 成员 | 说明 |
|---|---|
screen.virtualBounds | 整个虚拟桌面的边界。 |
screen.primary | 主显示器。 |
screen.displays | 所有显示器数组。 |
screen.contains(x, y) | 坐标归一化后是否落在某块显示器内;也接受点数组或对象。 |
screen.pointAt(ratioX, ratioY, displayIndex?) | 按 0..1 比例取得屏幕内的点;默认使用主屏。 |
边界和显示器对象包含:
index, deviceName, isPrimary,
left, top, right, bottom,
width, height, centerX, centerY
right 和 bottom 是不包含的边界。screen.pointAt(1, 1) 会返回屏幕内最后一个有效像素,不会返回边界外的点。
运行期间如果显示器布局发生变化,后续输入会停止并返回 SCREEN_TOPOLOGY_CHANGED。
sleep、console、input 和结果
等待
import { sleep } from "quicker";
sleep(500); // 0..10000 毫秒,可被取消
自动化脚本是同步运行时,不支持 await。需要短暂停顿时使用 sleep();等待和速率限制占用的时间都计入步骤超时。
日志
console 是全局对象,不需要从 quicker 导入:
console.log("位置", mouse.position());
console.info("开始");
console.warn("请检查目标窗口");
console.error("自定义错误信息");
日志进入组合动作运行日志。每次运行最多记录 100 条、总计 32,000 个字符;超过后丢弃后续日志并记录一次警告。
输入
input 来自步骤的 输入 参数,未提供时为 null。运行前 Quicker 会拍摄数据快照并递归冻结;修改 input 不会写回动作变量。
支持 null、布尔、文本、有限数字、数组和键为文本的普通对象。整数必须在 JavaScript 安全整数范围内;数据最多 16 层、10,000 个节点。图片、表格、函数、CLR 对象和循环引用等复杂值不支持。
输出结果
用 export default 把结果写到步骤的 结果 输出:
export default {
count: 3,
last: mouse.position()
};
没有 export default 时,脚本仍可成功,但不会设置 result。显式导出 null 会得到一个真实的空值结果。
结果支持的数据形状与输入相同。Promise、函数、Symbol、BigInt、循环引用、对象内部的 undefined 等值会被拒绝。
步骤参数和输出
脚本内容:要执行的 ESM JavaScript。Quicker 不会把它当成动作表达式求值。
输入:可绑定动作变量,供脚本中的 input 读取。
超时时间(毫秒):默认 30000,范围 100..120000。包括脚本计算、sleep()、平滑移动、按键保持、文本间隔和节流等待。
结束后恢复鼠标位置:正常结束、脚本错误或内部超时时,在输入清理状态可确认时尝试回到开始位置。用户接管或主动取消动作时不会强行恢复,以免把用户刚移动的鼠标拉走。
失败后停止:脚本失败时是否停止组合动作后续步骤。
输出包括:
- 是否成功(
isSuccess) - 结果(
result) - 错误码(
errorCode) - 错误消息(
errMessage)
用户接管或主动停止属于“动作已取消”,不是普通的脚本失败,因此不保证产生普通失败输出。
权限、用户接管和输入安全
- Quicker 会先静态分析从
"quicker"导入的能力。使用mouse、key或两者时,首次真实运行会分别请求鼠标、键盘或键鼠桌面自动化权限;权限确认前不会执行脚本或注入输入。 import * as qk from "quicker"可以访问全部当前导出,因此会按鼠标和键盘两种能力请求权限。只想申请必要能力时请使用命名导入。- 授权绑定动作、脚本、超时、恢复位置选项和固定配额策略;这些内容变化后需要重新确认。
- 授权只保存在当前账号的本机数据中,不随动作导出、分享、状态备份或同步到其它设备。
- 锁屏、UAC / 安全桌面下不会注入输入。鼠标操作会核对目标坐标下的窗口,键盘操作会核对当前前台窗口;管理员权限或高完整性目标一律拒绝,其它权限高于 Quicker 或权限无法确认的目标也会被拒绝。
- 启动时已经按住的动作触发键或鼠标按钮,需要在 1 秒内松开;新的按键、鼠标按钮或滚轮输入会立即由用户接管。
- 真实鼠标在 200 毫秒内累计移动约 5 个物理像素也会接管;极小的传感器抖动不会立刻中止。
- 如果已经配置 Quicker 的“停止运行中动作”全局热键,也可以用它取消正在执行的自动化脚本。
- 用户接管、主动取消、超时、异常或部分注入失败后,Quicker 会停止剩余输入,并尽力释放本次脚本按下的鼠标按钮和键盘按键。
- 已经发生的移动、点击、按键或文本输入不能回滚。失败只会阻止尚未执行的输入。
- 同一时间只能运行一个已支持输入互斥的自动化;冲突时返回
INPUT_BUSY,不会排队。部分旧输入模块暂不受此机制约束。
运行限制
这些限制按每次步骤运行计算,脚本不能修改:
| 项目 | 上限 |
|---|---|
| 脚本源码 | 100 KiB UTF-8 |
| JavaScript 内存 | 64 MiB |
| 执行语句数 | 500,000 |
| 函数递归深度 | 64 |
| 语法树节点 / 深度 | 100,000 / 256 |
| 桌面写操作(鼠标 API 或键盘事务) | 512 |
| 单击、双击和拖拽的按压事务 | 100 |
| 点击 / 拖拽按压速率 | 每秒 5 次,短时突发 2 次 |
| 垂直滚轮累计 | 120 click |
| 滚轮速率 | 每秒 20 click,短时突发 6 click |
| 键盘按下 / 释放边沿 | 4,096 |
| 键盘事务 | 256 |
| 键盘事务速率 | 每秒 20 次,短时突发 8 次 |
key.type() 文本 | 累计 2,000 个 UTF-16 代码单元 |
| 同时持有的按键 | 8 |
key.hotkey() 修饰键 | 4 |
| 单次平滑移动或拖拽 | 最长 2 秒、最多 120 个采样 |
| 平滑移动采样率 | 最多 60 Hz |
clickAll 点数 | 100 |
单次 sleep | 10 秒 |
| 日志 | 100 条、总计 32,000 字符 |
双击消耗 2 次鼠标按压额度,拖拽消耗 1 次。每次键盘 API 调用消耗 1 个键盘事务;down / up 各消耗 1 个边沿,press 消耗 2 个。节流等待仍计入步骤的总超时。
首版不支持的能力
async/await、Promise、setTimeout和后台任务- 动态
import()、其它静态模块、require()、npm 和 Node.js 模块 eval()、new Function()、CLR、反射和程序集访问- HTTP、文件、进程、剪贴板、浏览器 DOM、动作变量写回和子程序调用
- 独立
mouse.down()/mouse.up()、原始键码、扫描码和任意键盘布局映射 - 录制回放、图片定位、窗口句柄和窗口相对坐标;当前尚未导出
window - 水平滚轮、X1 / X2 按钮和任意点击次数
- 游戏级、驱动级或硬实时鼠标轨迹
需要这些能力时,请组合使用对应的 Quicker 步骤,不要试图从脚本绕过限制。
常见错误和排障
| 错误码 | 处理方法 |
|---|---|
EMPTY_SCRIPT、JS_PARSE_ERROR | 检查脚本是否为空、括号和引号是否配对。 |
IMPORT_NOT_ALLOWED | 只从 "quicker" 做命名导入或命名空间导入,不要使用 default import。 |
ASYNC_NOT_SUPPORTED、UNSUPPORTED_SYNTAX、STRING_COMPILATION_DISABLED | 删除异步、Promise、动态导入、命名导出、eval 或动态函数。 |
INVALID_ARGUMENT | 检查坐标、整数范围、按钮名、热键数组、文本和选项字段;不要传字符串数字。 |
KEY_NOT_SUPPORTED | 改用文档列出的封闭按键名称;不要传虚拟键码或扫描码。 |
KEY_ALREADY_HELD、KEY_NOT_HELD | 检查 key.down() / key.up() 是否成对,并优先改用 press() 或 hotkey()。 |
UNSUPPORTED_VALUE | 把输入或结果转换成简单值、数组和普通对象。 |
POINT_OUTSIDE_DISPLAY、INVALID_VIRTUAL_DESKTOP | 确认坐标落在实际显示器内,并检查主屏和多屏布局。 |
SCREEN_TOPOLOGY_CHANGED | 显示器布局在运行中改变;重新运行脚本。 |
TRUST_REQUIRED | 安装或保存动作后重新运行,并在本机确认当前脚本的桌面控制权限。 |
PHYSICAL_INPUT_ACTIVE | 松开触发动作时按住的键或鼠标按钮,再重新运行。 |
INPUT_BUSY | 另一个已接入协调器的输入自动化正在运行;等待它结束。 |
INPUT_MONITOR_UNAVAILABLE | Quicker 无法可靠监测用户接管;重新启动 Quicker 后再试。 |
WINDOWS_LOCKED、SECURE_DESKTOP、UNSAFE_DESKTOP | 解锁 Windows,关闭 UAC / 安全桌面后再运行。 |
ELEVATED_TARGET_DENIED、TARGET_PERMISSION_UNKNOWN | 管理员权限或高完整性目标一律不支持;其它目标也不能高于 Quicker,且必须能确认权限。 |
INPUT_LIMIT_EXCEEDED、LIMIT_EXCEEDED | 减少点击、滚轮、按键、文本、循环、源码规模或复杂度。 |
TIMEOUT | 减少工作量,或谨慎提高步骤的超时时间。 |
INPUT_INJECTION_FAILED、INPUT_OPERATION_FAILED、HOST_OPERATION_FAILED | 输入未能完整发送;检查系统状态和目标窗口,再从安全位置重试。 |
INPUT_CLEANUP_FAILED | Quicker 无法确认本次脚本持有的按键已完全释放;先人工松开相关按键并检查系统输入状态。 |
JS_RUNTIME_ERROR | 查看 错误消息 和动作运行日志,定位普通 JavaScript 运行错误。 |
相关链接
更新历史
- 2026-08-13 首次加入自动化脚本模块文档,提供受控的鼠标和键盘 API。