blur-autoclicker-automation
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBlur AutoClicker Automation
Blur AutoClicker 自动化工具
Skill by ara.so — Devtools Skills collection.
Blur AutoClicker is a high-performance Windows auto-clicker built with TypeScript and Tauri that provides precise CPS (clicks per second) control up to 500 CPS, keyboard automation, position clicking, and advanced timing features. It combines a web-based UI with Rust backend for optimal performance while maintaining under 100MB RAM usage.
由ara.so开发的工具 — 开发者工具技能合集。
Blur AutoClicker是一款基于TypeScript和Tauri构建的高性能Windows自动点击器,提供最高可达500次/秒(CPS,clicks per second)的精准点击控制、键盘自动化、定点点击以及高级定时功能。它结合了Web界面与Rust后端,在保持性能最优的同时,内存占用始终低于100MB。
Installation
安装
End User Installation
终端用户安装
Download the latest release from GitHub:
powershell
undefined从GitHub下载最新版本:
powershell
undefinedDefault installation location
默认安装路径
%localappdata%\BlurAutoClicker\BlurAutoClicker.exe
%localappdata%\BlurAutoClicker\BlurAutoClicker.exe
Config and stats location
配置文件及统计数据路径
%appdata%\BlurAutoClicker
undefined%appdata%\BlurAutoClicker
undefinedDevelopment Setup
开发环境搭建
Requirements:
- Node.js 20 or newer
- Rust via rustup
- Microsoft C++ Build Tools / Visual Studio Build Tools
powershell
undefined前置要求:
- Node.js 20或更高版本
- 通过rustup安装Rust
- Microsoft C++构建工具 / Visual Studio构建工具
powershell
undefinedClone the repository
克隆仓库
git clone https://github.com/Blur009/Blur-AutoClicker.git
cd Blur-AutoClicker
git clone https://github.com/Blur009/Blur-AutoClicker.git
cd Blur-AutoClicker
Install dependencies
安装依赖
npm install
npm install
Set up Rust toolchain
设置Rust工具链
rustup default stable-x86_64-pc-windows-msvc
undefinedrustup default stable-x86_64-pc-windows-msvc
undefinedDevelopment Commands
开发命令
powershell
undefinedpowershell
undefinedRun in development mode
启动开发模式
npm run dev
npm run dev
Build release bundle
构建发布包
npm run build
npm run build
Lint code
代码检查
npm run lint
npm run lint
Build frontend only
仅构建前端
npm run frontend:build
npm run frontend:build
Run Rust tests
运行Rust测试
cargo test --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml
Check Rust code
检查Rust代码
cargo check --manifest-path src-tauri/Cargo.toml
Built installer location: `src-tauri/target/release/bundle/nsis/`cargo check --manifest-path src-tauri/Cargo.toml
生成的安装包路径:`src-tauri/target/release/bundle/nsis/`Project Structure
项目结构
Blur-AutoClicker/
├── src/ # TypeScript frontend (web UI)
├── src-tauri/ # Rust backend (Tauri)
│ ├── src/ # Rust source code
│ ├── Cargo.toml # Rust dependencies
│ └── tauri.conf.json # Tauri configuration
├── public/ # Static assets
└── package.json # Node.js dependenciesBlur-AutoClicker/
├── src/ # TypeScript前端(Web界面)
├── src-tauri/ # Rust后端(Tauri)
│ ├── src/ # Rust源代码
│ ├── Cargo.toml # Rust依赖配置
│ └── tauri.conf.json # Tauri配置文件
├── public/ # 静态资源
└── package.json # Node.js依赖配置Core Features
核心功能
1. Mouse Button Control
1. 鼠标按键控制
The application supports left, right, and middle mouse button clicking:
typescript
// Example configuration for mouse button selection
interface MouseConfig {
button: 'left' | 'right' | 'middle';
mode: 'hold' | 'toggle';
cps: number; // Clicks per second (max 500)
}
const config: MouseConfig = {
button: 'left',
mode: 'toggle',
cps: 50
};应用支持左键、右键和中键点击:
typescript
// 鼠标按键选择配置示例
interface MouseConfig {
button: 'left' | 'right' | 'middle';
mode: 'hold' | 'toggle';
cps: number; // 点击次数/秒(最高500)
}
const config: MouseConfig = {
button: 'left',
mode: 'toggle',
cps: 50
};2. Keyboard Key Automation
2. 键盘按键自动化
Automate keyboard key presses with case control:
typescript
interface KeyConfig {
key: string;
uppercase: boolean;
mode: 'hold' | 'toggle';
pressesPerSecond: number;
}
const keyConfig: KeyConfig = {
key: 'a',
uppercase: false,
mode: 'hold',
pressesPerSecond: 10
};支持带大小写控制的键盘按键自动触发:
typescript
interface KeyConfig {
key: string;
uppercase: boolean;
mode: 'hold' | 'toggle';
pressesPerSecond: number;
}
const keyConfig: KeyConfig = {
key: 'a',
uppercase: false,
mode: 'hold',
pressesPerSecond: 10
};3. Click Timing (Duty Cycle)
3. 点击时序(工作周期)
Control the timing between press and release:
typescript
interface TimingConfig {
clickDuration: number; // milliseconds
interval: number; // milliseconds between clicks
}
// For 50 CPS with 50% duty cycle
const timing: TimingConfig = {
clickDuration: 10, // 10ms press
interval: 20 // 20ms total (1000ms / 50 CPS)
};控制按下与释放之间的时间间隔:
typescript
interface TimingConfig {
clickDuration: number; // 毫秒
interval: number; // 点击间隔毫秒数
}
// 50 CPS且工作周期50%的配置
const timing: TimingConfig = {
clickDuration: 10, // 按下10毫秒
interval: 20 // 总间隔20毫秒(1000ms / 50 CPS)
};4. Speed Range Mode
4. 速度范围模式
Randomize CPS within a range:
typescript
interface SpeedRangeConfig {
enabled: boolean;
minCps: number;
maxCps: number;
}
const speedRange: SpeedRangeConfig = {
enabled: true,
minCps: 40,
maxCps: 60
};在指定范围内随机化CPS:
typescript
interface SpeedRangeConfig {
enabled: boolean;
minCps: number;
maxCps: number;
}
const speedRange: SpeedRangeConfig = {
enabled: true,
minCps: 40,
maxCps: 60
};5. Position Clicking
5. 定点点击
Click at specific screen coordinates:
typescript
interface PositionConfig {
enabled: boolean;
x: number;
y: number;
moveBeforeClick: boolean;
}
const positionClick: PositionConfig = {
enabled: true,
x: 1920,
y: 1080,
moveBeforeClick: true
};在特定屏幕坐标处点击:
typescript
interface PositionConfig {
enabled: boolean;
x: number;
y: number;
moveBeforeClick: boolean;
}
const positionClick: PositionConfig = {
enabled: true,
x: 1920,
y: 1080,
moveBeforeClick: true
};6. Click and Time Limits
6. 点击次数与时间限制
Stop after specific conditions:
typescript
interface LimitsConfig {
clickLimit?: number; // Stop after X clicks
timeLimit?: number; // Stop after X seconds
}
const limits: LimitsConfig = {
clickLimit: 1000,
timeLimit: 60 // 60 seconds
};满足特定条件后自动停止:
typescript
interface LimitsConfig {
clickLimit?: number; // 点击X次后停止
timeLimit?: number; // 运行X秒后停止
}
const limits: LimitsConfig = {
clickLimit: 1000,
timeLimit: 60 // 60秒
};7. Corner and Edge Stopping
7. 边角停止
Automatically stop when mouse reaches screen edges:
typescript
interface EdgeStoppingConfig {
enabled: boolean;
cornerThreshold: number; // pixels from corner
edgeThreshold: number; // pixels from edge
}
const edgeStopping: EdgeStoppingConfig = {
enabled: true,
cornerThreshold: 50,
edgeThreshold: 10
};鼠标到达屏幕边缘时自动停止:
typescript
interface EdgeStoppingConfig {
enabled: boolean;
cornerThreshold: number; // 距离边角的像素数
edgeThreshold: number; // 距离边缘的像素数
}
const edgeStopping: EdgeStoppingConfig = {
enabled: true,
cornerThreshold: 50,
edgeThreshold: 10
};Tauri Backend Integration
Tauri后端集成
Tauri Commands
Tauri命令
When developing features, interact with the Rust backend via Tauri commands:
typescript
import { invoke } from '@tauri-apps/api/tauri';
// Start clicking
async function startClicking(config: ClickConfig): Promise<void> {
await invoke('start_clicking', { config });
}
// Stop clicking
async function stopClicking(): Promise<void> {
await invoke('stop_clicking');
}
// Get click stats
async function getStats(): Promise<ClickStats> {
return await invoke('get_stats');
}
interface ClickStats {
totalClicks: number;
currentCps: number;
averageCps: number;
uptime: number;
}开发功能时,通过Tauri命令与Rust后端交互:
typescript
import { invoke } from '@tauri-apps/api/tauri';
// 开始点击
async function startClicking(config: ClickConfig): Promise<void> {
await invoke('start_clicking', { config });
}
// 停止点击
async function stopClicking(): Promise<void> {
await invoke('stop_clicking');
}
// 获取点击统计
async function getStats(): Promise<ClickStats> {
return await invoke('get_stats');
}
interface ClickStats {
totalClicks: number;
currentCps: number;
averageCps: number;
uptime: number;
}Rust Backend Example
Rust后端示例
rust
// src-tauri/src/main.rs
use tauri::State;
use std::sync::Mutex;
struct ClickerState {
is_active: bool,
total_clicks: u64,
}
#[tauri::command]
fn start_clicking(state: State<Mutex<ClickerState>>) -> Result<(), String> {
let mut clicker = state.lock().unwrap();
clicker.is_active = true;
Ok(())
}
#[tauri::command]
fn stop_clicking(state: State<Mutex<ClickerState>>) -> Result<(), String> {
let mut clicker = state.lock().unwrap();
clicker.is_active = false;
Ok(())
}
#[tauri::command]
fn get_stats(state: State<Mutex<ClickerState>>) -> Result<u64, String> {
let clicker = state.lock().unwrap();
Ok(clicker.total_clicks)
}rust
// src-tauri/src/main.rs
use tauri::State;
use std::sync::Mutex;
struct ClickerState {
is_active: bool,
total_clicks: u64,
}
#[tauri::command]
fn start_clicking(state: State<Mutex<ClickerState>>) -> Result<(), String> {
let mut clicker = state.lock().unwrap();
clicker.is_active = true;
Ok(())
}
#[tauri::command]
fn stop_clicking(state: State<Mutex<ClickerState>>) -> Result<(), String> {
let mut clicker = state.lock().unwrap();
clicker.is_active = false;
Ok(())
}
#[tauri::command]
fn get_stats(state: State<Mutex<ClickerState>>) -> Result<u64, String> {
let clicker = state.lock().unwrap();
Ok(clicker.total_clicks)
}Configuration Management
配置管理
Saving Configuration
保存配置
typescript
import { appDataDir } from '@tauri-apps/api/path';
import { writeTextFile, readTextFile } from '@tauri-apps/api/fs';
async function saveConfig(config: AppConfig): Promise<void> {
const appData = await appDataDir();
const configPath = `${appData}/config.json`;
await writeTextFile(configPath, JSON.stringify(config, null, 2));
}
async function loadConfig(): Promise<AppConfig | null> {
try {
const appData = await appDataDir();
const configPath = `${appData}/config.json`;
const content = await readTextFile(configPath);
return JSON.parse(content);
} catch (error) {
console.error('Failed to load config:', error);
return null;
}
}
interface AppConfig {
mouseButton: 'left' | 'right' | 'middle';
mode: 'hold' | 'toggle';
cps: number;
hotkey: string;
advanced: AdvancedConfig;
}
interface AdvancedConfig {
dutyCycle: number;
speedRange?: SpeedRangeConfig;
positionClick?: PositionConfig;
limits?: LimitsConfig;
edgeStopping?: EdgeStoppingConfig;
}typescript
import { appDataDir } from '@tauri-apps/api/path';
import { writeTextFile, readTextFile } from '@tauri-apps/api/fs';
async function saveConfig(config: AppConfig): Promise<void> {
const appData = await appDataDir();
const configPath = `${appData}/config.json`;
await writeTextFile(configPath, JSON.stringify(config, null, 2));
}
async function loadConfig(): Promise<AppConfig | null> {
try {
const appData = await appDataDir();
const configPath = `${appData}/config.json`;
const content = await readTextFile(configPath);
return JSON.parse(content);
} catch (error) {
console.error('加载配置失败:', error);
return null;
}
}
interface AppConfig {
mouseButton: 'left' | 'right' | 'middle';
mode: 'hold' | 'toggle';
cps: number;
hotkey: string;
advanced: AdvancedConfig;
}
interface AdvancedConfig {
dutyCycle: number;
speedRange?: SpeedRangeConfig;
positionClick?: PositionConfig;
limits?: LimitsConfig;
edgeStopping?: EdgeStoppingConfig;
}Hotkey Management
热键管理
typescript
import { register, unregister } from '@tauri-apps/api/globalShortcut';
async function setupHotkeys(hotkey: string): Promise<void> {
// Unregister previous hotkey
await unregister(hotkey).catch(() => {});
// Register new hotkey
await register(hotkey, async () => {
// Toggle clicking state
const isActive = await invoke('is_clicking_active');
if (isActive) {
await invoke('stop_clicking');
} else {
await invoke('start_clicking');
}
});
}
// Common hotkey combinations
const hotkeyExamples = [
'F6',
'F7',
'F8',
'Ctrl+Shift+A',
'Alt+C'
];typescript
import { register, unregister } from '@tauri-apps/api/globalShortcut';
async function setupHotkeys(hotkey: string): Promise<void> {
// 注销之前的热键
await unregister(hotkey).catch(() => {});
// 注册新热键
await register(hotkey, async () => {
// 切换点击状态
const isActive = await invoke('is_clicking_active');
if (isActive) {
await invoke('stop_clicking');
} else {
await invoke('start_clicking');
}
});
}
// 常见热键组合
const hotkeyExamples = [
'F6',
'F7',
'F8',
'Ctrl+Shift+A',
'Alt+C'
];Performance Optimization
性能优化
Timer Resolution
定时器精度
rust
// src-tauri/src/timer.rs
use std::time::{Duration, Instant};
use std::thread;
pub struct PrecisionTimer {
interval: Duration,
last_tick: Instant,
}
impl PrecisionTimer {
pub fn new(cps: u32) -> Self {
let interval = Duration::from_micros(1_000_000 / cps as u64);
Self {
interval,
last_tick: Instant::now(),
}
}
pub fn wait_for_next_tick(&mut self) {
let elapsed = self.last_tick.elapsed();
if elapsed < self.interval {
thread::sleep(self.interval - elapsed);
}
self.last_tick = Instant::now();
}
}
// Usage
let mut timer = PrecisionTimer::new(50); // 50 CPS
loop {
// Perform click
send_click();
timer.wait_for_next_tick();
}rust
// src-tauri/src/timer.rs
use std::time::{Duration, Instant};
use std::thread;
pub struct PrecisionTimer {
interval: Duration,
last_tick: Instant,
}
impl PrecisionTimer {
pub fn new(cps: u32) -> Self {
let interval = Duration::from_micros(1_000_000 / cps as u64);
Self {
interval,
last_tick: Instant::now(),
}
}
pub fn wait_for_next_tick(&mut self) {
let elapsed = self.last_tick.elapsed();
if elapsed < self.interval {
thread::sleep(self.interval - elapsed);
}
self.last_tick = Instant::now();
}
}
// 使用示例
let mut timer = PrecisionTimer::new(50); // 50 CPS
loop {
// 执行点击
send_click();
timer.wait_for_next_tick();
}Memory Management
内存管理
Keep RAM usage under 100MB:
typescript
// Clear click history periodically
let clickHistory: number[] = [];
const MAX_HISTORY_SIZE = 1000;
function recordClick(timestamp: number): void {
clickHistory.push(timestamp);
// Keep only recent clicks
if (clickHistory.length > MAX_HISTORY_SIZE) {
clickHistory = clickHistory.slice(-MAX_HISTORY_SIZE);
}
}
function calculateCps(): number {
const now = Date.now();
const recentClicks = clickHistory.filter(t => now - t < 1000);
return recentClicks.length;
}保持内存占用低于100MB:
typescript
// 定期清理点击历史
let clickHistory: number[] = [];
const MAX_HISTORY_SIZE = 1000;
function recordClick(timestamp: number): void {
clickHistory.push(timestamp);
// 仅保留最近的点击记录
if (clickHistory.length > MAX_HISTORY_SIZE) {
clickHistory = clickHistory.slice(-MAX_HISTORY_SIZE);
}
}
function calculateCps(): number {
const now = Date.now();
const recentClicks = clickHistory.filter(t => now - t < 1000);
return recentClicks.length;
}Building for Release
构建发布版本
Windows Release Process
Windows发布流程
powershell
undefinedpowershell
undefined1. Update version in package.json and Cargo.toml
1. 更新package.json和Cargo.toml中的版本号
2. Clean previous builds
2. 清理之前的构建产物
Remove-Item -Recurse -Force src-tauri/target/release/bundle -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force src-tauri/target/release/bundle -ErrorAction SilentlyContinue
3. Build release
3. 构建发布版本
npm run build
npm run build
4. Installer location
4. 安装包路径
src-tauri/target/release/bundle/nsis/Blur-AutoClicker_X.X.X_x64-setup.exe
src-tauri/target/release/bundle/nsis/Blur-AutoClicker_X.X.X_x64-setup.exe
5. Test installer
5. 测试安装包
Start-Process "src-tauri\target\release\bundle\nsis*.exe"
undefinedStart-Process "src-tauri\target\release\bundle\nsis*.exe"
undefinedCode Signing (Optional)
代码签名(可选)
powershell
undefinedpowershell
undefinedNote: Windows Authenticode signing is separate from Tauri updater signing
注意:Windows Authenticode签名与Tauri更新器签名是分开的
See docs/windows-release-trust.md for complete signing instructions
完整签名说明请查看docs/windows-release-trust.md
Environment variables needed for signing
签名所需环境变量
WINDOWS_CERTIFICATE (base64 certificate)
WINDOWS_CERTIFICATE(base64格式证书)
WINDOWS_CERTIFICATE_PASSWORD (certificate password)
WINDOWS_CERTIFICATE_PASSWORD(证书密码)
undefinedundefinedCommon Development Patterns
常见开发模式
Creating a Custom Click Mode
创建自定义点击模式
typescript
// src/lib/modes/customMode.ts
interface CustomModeConfig {
pattern: number[]; // Array of delays in milliseconds
repeat: boolean;
}
class CustomClickMode {
private config: CustomModeConfig;
private patternIndex: number = 0;
constructor(config: CustomModeConfig) {
this.config = config;
}
getNextDelay(): number {
const delay = this.config.pattern[this.patternIndex];
this.patternIndex = (this.patternIndex + 1) % this.config.pattern.length;
return delay;
}
async executePattern(): Promise<void> {
do {
for (const delay of this.config.pattern) {
await invoke('send_click');
await new Promise(resolve => setTimeout(resolve, delay));
}
} while (this.config.repeat);
}
}
// Usage: Click with pattern [100ms, 200ms, 100ms, 500ms]
const customMode = new CustomClickMode({
pattern: [100, 200, 100, 500],
repeat: true
});typescript
// src/lib/modes/customMode.ts
interface CustomModeConfig {
pattern: number[]; // 毫秒级延迟数组
repeat: boolean;
}
class CustomClickMode {
private config: CustomModeConfig;
private patternIndex: number = 0;
constructor(config: CustomModeConfig) {
this.config = config;
}
getNextDelay(): number {
const delay = this.config.pattern[this.patternIndex];
this.patternIndex = (this.patternIndex + 1) % this.config.pattern.length;
return delay;
}
async executePattern(): Promise<void> {
do {
for (const delay of this.config.pattern) {
await invoke('send_click');
await new Promise(resolve => setTimeout(resolve, delay));
}
} while (this.config.repeat);
}
}
// 使用示例:按照[100ms, 200ms, 100ms, 500ms]的模式点击
const customMode = new CustomClickMode({
pattern: [100, 200, 100, 500],
repeat: true
});Statistics Tracking
统计数据追踪
typescript
// src/lib/stats.ts
interface ClickStatistics {
totalClicks: number;
sessionClicks: number;
averageCps: number;
peakCps: number;
uptime: number; // seconds
startTime: number;
}
class StatsTracker {
private stats: ClickStatistics;
private clickTimestamps: number[] = [];
constructor() {
this.stats = {
totalClicks: 0,
sessionClicks: 0,
averageCps: 0,
peakCps: 0,
uptime: 0,
startTime: Date.now()
};
}
recordClick(): void {
const now = Date.now();
this.stats.totalClicks++;
this.stats.sessionClicks++;
this.clickTimestamps.push(now);
// Keep only last second of clicks
const oneSecondAgo = now - 1000;
this.clickTimestamps = this.clickTimestamps.filter(t => t > oneSecondAgo);
const currentCps = this.clickTimestamps.length;
if (currentCps > this.stats.peakCps) {
this.stats.peakCps = currentCps;
}
}
getStats(): ClickStatistics {
this.stats.uptime = Math.floor((Date.now() - this.stats.startTime) / 1000);
this.stats.averageCps = this.stats.uptime > 0
? this.stats.sessionClicks / this.stats.uptime
: 0;
return { ...this.stats };
}
async save(): Promise<void> {
await saveConfig({ stats: this.stats });
}
}typescript
// src/lib/stats.ts
interface ClickStatistics {
totalClicks: number;
sessionClicks: number;
averageCps: number;
peakCps: number;
uptime: number; // 秒
startTime: number;
}
class StatsTracker {
private stats: ClickStatistics;
private clickTimestamps: number[] = [];
constructor() {
this.stats = {
totalClicks: 0,
sessionClicks: 0,
averageCps: 0,
peakCps: 0,
uptime: 0,
startTime: Date.now()
};
}
recordClick(): void {
const now = Date.now();
this.stats.totalClicks++;
this.stats.sessionClicks++;
this.clickTimestamps.push(now);
// 仅保留最近一秒的点击记录
const oneSecondAgo = now - 1000;
this.clickTimestamps = this.clickTimestamps.filter(t => t > oneSecondAgo);
const currentCps = this.clickTimestamps.length;
if (currentCps > this.stats.peakCps) {
this.stats.peakCps = currentCps;
}
}
getStats(): ClickStatistics {
this.stats.uptime = Math.floor((Date.now() - this.stats.startTime) / 1000);
this.stats.averageCps = this.stats.uptime > 0
? this.stats.sessionClicks / this.stats.uptime
: 0;
return { ...this.stats };
}
async save(): Promise<void> {
await saveConfig({ stats: this.stats });
}
}Troubleshooting
故障排查
Windows SmartScreen Warning
Windows SmartScreen警告
The application shows SmartScreen warnings for unsigned installers:
- This is normal for open-source GitHub releases
- See for signing information
docs/windows-release-trust.md - Users can click "More info" → "Run anyway"
未签名的安装包会触发SmartScreen警告:
- 这对于GitHub开源发布的软件是正常现象
- 签名相关信息请查看
docs/windows-release-trust.md - 用户可以点击“更多信息”→“仍要运行”
CPS Accuracy Issues
CPS精度问题
If actual CPS doesn't match configured CPS:
typescript
// Enable debug logging
const DEBUG = true;
async function debugClickAccuracy(targetCps: number, duration: number): Promise<void> {
const clicks: number[] = [];
const startTime = Date.now();
while (Date.now() - startTime < duration) {
const clickTime = Date.now();
await invoke('send_click');
clicks.push(clickTime);
if (DEBUG) {
// Calculate actual CPS every second
const recentClicks = clicks.filter(t => clickTime - t < 1000);
console.log(`Target: ${targetCps} CPS, Actual: ${recentClicks.length} CPS`);
}
}
// Final accuracy report
const totalTime = (Date.now() - startTime) / 1000;
const actualCps = clicks.length / totalTime;
const accuracy = (actualCps / targetCps) * 100;
console.log(`Accuracy: ${accuracy.toFixed(2)}%`);
}如果实际CPS与配置值不符:
typescript
// 启用调试日志
const DEBUG = true;
async function debugClickAccuracy(targetCps: number, duration: number): Promise<void> {
const clicks: number[] = [];
const startTime = Date.now();
while (Date.now() - startTime < duration) {
const clickTime = Date.now();
await invoke('send_click');
clicks.push(clickTime);
if (DEBUG) {
// 每秒计算一次实际CPS
const recentClicks = clicks.filter(t => clickTime - t < 1000);
console.log(`目标CPS: ${targetCps}, 实际CPS: ${recentClicks.length}`);
}
}
// 最终精度报告
const totalTime = (Date.now() - startTime) / 1000;
const actualCps = clicks.length / totalTime;
const accuracy = (actualCps / targetCps) * 100;
console.log(`精度: ${accuracy.toFixed(2)}%`);
}High RAM Usage
内存占用过高
If RAM usage exceeds 100MB:
typescript
// Monitor memory usage
if (performance.memory) {
const usedMemory = performance.memory.usedJSHeapSize / 1024 / 1024;
console.log(`Memory usage: ${usedMemory.toFixed(2)} MB`);
if (usedMemory > 80) {
// Clear unnecessary data
clickHistory = clickHistory.slice(-100);
// Force garbage collection (if available)
if (global.gc) global.gc();
}
}如果内存占用超过100MB:
typescript
// 监控内存使用情况
if (performance.memory) {
const usedMemory = performance.memory.usedJSHeapSize / 1024 / 1024;
console.log(`内存占用: ${usedMemory.toFixed(2)} MB`);
if (usedMemory > 80) {
// 清理不必要的数据
clickHistory = clickHistory.slice(-100);
// 强制垃圾回收(如果支持)
if (global.gc) global.gc();
}
}Build Errors
构建错误
powershell
undefinedpowershell
undefinedClean install
重新安装依赖
Remove-Item -Recurse -Force node_modules
Remove-Item package-lock.json
npm install
Remove-Item -Recurse -Force node_modules
Remove-Item package-lock.json
npm install
Clean Rust build
清理Rust构建产物
cargo clean --manifest-path src-tauri/Cargo.toml
cargo clean --manifest-path src-tauri/Cargo.toml
Update Rust toolchain
更新Rust工具链
rustup update stable-x86_64-pc-windows-msvc
rustup update stable-x86_64-pc-windows-msvc
Rebuild
重新构建
npm run build
undefinednpm run build
undefinedTauri Command Not Found
Tauri命令未找到
typescript
// Ensure proper Tauri API imports
import { invoke } from '@tauri-apps/api/tauri';
// Check Tauri configuration
// src-tauri/tauri.conf.json
{
"tauri": {
"allowlist": {
"all": false,
"fs": {
"all": false,
"readFile": true,
"writeFile": true
},
"globalShortcut": {
"all": true
}
}
}
}typescript
// 确保正确导入Tauri API
import { invoke } from '@tauri-apps/api/tauri';
// 检查Tauri配置
// src-tauri/tauri.conf.json
{
"tauri": {
"allowlist": {
"all": false,
"fs": {
"all": false,
"readFile": true,
"writeFile": true
},
"globalShortcut": {
"all": true
}
}
}
}Testing
测试
typescript
// Example test for click accuracy
describe('Click Accuracy', () => {
it('should click at specified CPS within 5% tolerance', async () => {
const targetCps = 50;
const duration = 5000; // 5 seconds
const tolerance = 0.05; // 5%
const clicks = await testClickAccuracy(targetCps, duration);
const actualCps = clicks.length / (duration / 1000);
const lowerBound = targetCps * (1 - tolerance);
const upperBound = targetCps * (1 + tolerance);
expect(actualCps).toBeGreaterThanOrEqual(lowerBound);
expect(actualCps).toBeLessThanOrEqual(upperBound);
});
});typescript
// 点击精度测试示例
describe('点击精度', () => {
it('应在指定CPS的5%误差范围内点击', async () => {
const targetCps = 50;
const duration = 5000; // 5秒
const tolerance = 0.05; // 5%
const clicks = await testClickAccuracy(targetCps, duration);
const actualCps = clicks.length / (duration / 1000);
const lowerBound = targetCps * (1 - tolerance);
const upperBound = targetCps * (1 + tolerance);
expect(actualCps).toBeGreaterThanOrEqual(lowerBound);
expect(actualCps).toBeLessThanOrEqual(upperBound);
});
});License
许可证
GPL-3.0 - See LICENSE.md
GPL-3.0 - 查看LICENSE.md