目录

概述 规则格式 规则类型详解 导入与导出 自定义脚本 脚本 API 参考 脚本示例 调试技巧 常见问题

MirageX 脚本开发文档

学习如何编写规则和自定义脚本,扩展 MirageX 的页面处理能力

概述

MirageX 提供两种扩展方式:

方式适用场景难度说明
JSON 规则文本替换、隐藏元素、金额格式化⭐ 简单声明式 JSON 配置,无需编程基础
自定义脚本复杂 DOM 操作、动态内容、多步骤处理⭐⭐ 进阶JavaScript 代码,拥有完整的 DOM 操作能力

如何选择?

用「导入规则」如果你只需要:

用「导入脚本」如果你需要:

内置功能:转账检测 v2.2

MirageX v2.2+ 内置了转账页面自动检测功能。当你打开转账页面并输入金额后,扩展会自动弹出确认框,确认后自动从虚拟余额中扣减。此功能无需手动配置,自动适配所有银行的转账页面。

两种方式都可以通过 popup 面板的「导入规则」和「导入脚本」按钮加载,也可以通过程序化方式批量部署。

规则格式

规则是一个 JSON 数组,每条规则定义一个页面操作。基本结构:

[
  {
    "searchText": "要搜索的文本",
    "searchType": "exact",
    "newValue": "替换后的值",
    "action": "replace",
    "amountOnly": false
  }
]

字段说明

字段类型必填说明
searchTextstring在页面中搜索的文本内容
searchTypestring搜索方式:exact(精确匹配)、prefix(前缀匹配)、contains(包含匹配)
newValuestring替换后的新值(hide 操作留空)
actionstring操作类型:replacehide
amountOnlyboolean是否只替换金额部分(保留前缀文字)。默认 false

搜索类型详解

searchType行为示例
exact文本完全一致才匹配"Hello World" 只匹配 "Hello World"
prefix文本以 searchText 开头"总计:" 匹配 "总计:1,234.56"
contains文本包含 searchText"订单号" 匹配 "您的订单号是 ABC123"

规则类型详解

replace — 替换文本

将匹配到的文本节点替换为新值。

[
  {
    "searchText": "Hello World",
    "searchType": "exact",
    "newValue": "你好世界",
    "action": "replace"
  }
]

replace + amountOnly — 只替换金额

当页面文本为 "总计:1,234.56",你只想改数字不改前缀时使用。

[
  {
    "searchText": "总计:",
    "searchType": "prefix",
    "newValue": "9,999,999.00",
    "action": "replace",
    "amountOnly": true
  }
]

这段规则的效果:找到以 "总计:" 开头的文本,只把其中的数字部分替换为 9,999,999.00,结果变为 "总计:9,999,999.00"

hide — 隐藏元素

隐藏包含匹配文本的整行(<tr><li>)。

[
  {
    "searchText": "测试数据行",
    "searchType": "contains",
    "newValue": "",
    "action": "hide"
  }
]

多条规则组合

一个页面可以有多条规则,它们会全部执行:

[
  {
    "searchText": "商品单价:",
    "searchType": "prefix",
    "newValue": "1,299.00",
    "action": "replace",
    "amountOnly": true
  },
  {
    "searchText": "订单总额:",
    "searchType": "prefix",
    "newValue": "1,299.00",
    "action": "replace",
    "amountOnly": true
  },
  {
    "searchText": "优惠券抵扣",
    "searchType": "contains",
    "newValue": "",
    "action": "hide"
  },
  {
    "searchText": "物流状态:已发货",
    "searchType": "exact",
    "newValue": "物流状态:待发货",
    "action": "replace"
  }
]

导入与导出

导出规则

  1. 在目标页面上通过 AI 执行修改,或手动导入规则
  2. 点击 popup 面板底部的「导出规则」按钮
  3. 当前生效的所有规则会以 JSON 格式复制到剪贴板
  4. 将 JSON 文本保存到本地文件(如 my-rules.json),下次直接粘贴导入

导入规则

  1. 打开目标页面
  2. 点击 popup 面板底部的「导入规则」按钮
  3. 在弹窗中粘贴规则 JSON 文本
  4. 点击确定,规则立即生效并自动缓存(下次打开自动恢复)
缓存机制:导入的规则会自动保存到本地。页面刷新、关闭浏览器后重新打开同一页面,规则会自动恢复生效,无需重新导入。点击「还原页面」可清除缓存。

自定义脚本

当规则无法满足需求时(如需要条件判断、循环、动态计算、操作多个元素等),可以编写 JavaScript 脚本。

导入方式

  1. 点击 popup 面板底部的「导入脚本」按钮
  2. 输入 URL 匹配规则(如 *://*.example.com/*),符合规则的页面才会执行
  3. 粘贴 JavaScript 代码
  4. 输入执行间隔0 = 只执行一次;2000 = 每 2 秒重复执行
  5. 点击确定,脚本立即运行并保存,以后打开匹配的页面自动执行

脚本运行环境

特性说明
运行位置页面内容脚本环境(Content Script),与页面共享 DOM
可用 APIdocumentwindowconsolesetTimeoutsetIntervalfetch
ES 版本支持 ES5 / ES6 语法(取决于浏览器版本)
限制无法访问 chrome.* API,无法跨域请求(受页面 CSP 限制)
安全沙盒脚本的 windowdocument 是真实页面环境

脚本 API 参考

脚本中可以直接使用以下 DOM 操作方法:

查找元素

// CSS 选择器
var el = document.querySelector('.price');
var els = document.querySelectorAll('table tr');

// 文本内容查找
function findByText(selector, text) {
  var elements = document.querySelectorAll(selector);
  for (var i = 0; i < elements.length; i++) {
    if (elements[i].textContent.indexOf(text) !== -1) {
      return elements[i];
    }
  }
  return null;
}

修改文本

// 修改元素文本
el.textContent = '新文本';

// 修改 HTML(注意安全)
el.innerHTML = '<span>新内容</span>';

// 修改 input 值
input.value = '新值';
input.dispatchEvent(new Event('input', { bubbles: true }));
input.dispatchEvent(new Event('change', { bubbles: true }));

修改样式

// 单个样式
el.style.color = 'red';
el.style.fontWeight = 'bold';
el.style.display = 'none';

// 批量样式
Object.assign(el.style, {
  color: '#ff0000',
  backgroundColor: '#fff3cd',
  fontWeight: 'bold',
  fontSize: '16px'
});

// 添加/移除 CSS 类
el.classList.add('highlight');
el.classList.remove('hidden');

操作表格行

// 隐藏一行
function hideRow(text) {
  var rows = document.querySelectorAll('tr');
  for (var i = 0; i < rows.length; i++) {
    if (rows[i].textContent.indexOf(text) !== -1) {
      rows[i].style.display = 'none';
    }
  }
}

// 在表格末尾添加一行
var table = document.querySelector('table tbody') || document.querySelector('table');
if (table) {
  var tr = document.createElement('tr');
  tr.innerHTML = '<td>数据1</td><td>数据2</td><td>数据3</td>';
  table.appendChild(tr);
}

// 在指定行之后插入
function insertRowAfter(targetText, html) {
  var rows = document.querySelectorAll('tr');
  for (var i = 0; i < rows.length; i++) {
    if (rows[i].textContent.indexOf(targetText) !== -1) {
      var newRow = document.createElement('tr');
      newRow.innerHTML = html;
      rows[i].parentNode.insertBefore(newRow, rows[i].nextSibling);
      break;
    }
  }
}

延迟执行(等待元素出现)

function waitAndExecute(selector, callback, maxWait) {
  maxWait = maxWait || 10000;
  var start = Date.now();

  function check() {
    var el = document.querySelector(selector);
    if (el) {
      callback(el);
    } else if (Date.now() - start < maxWait) {
      setTimeout(check, 300);
    }
  }
  check();
}

// 用法:等待 .price 元素出现后修改
waitAndExecute('.price', function(el) {
  el.textContent = '1,299.00';
});

脚本示例

示例 1:替换页面标题和副标题

document.title = '我的自定义标题';

var h1 = document.querySelector('h1');
if (h1) h1.textContent = '欢迎来到我的网站';

var subtitle = document.querySelector('.subtitle');
if (subtitle) subtitle.textContent = '这是副标题';

示例 2:高亮包含特定关键字的行

var keyword = '重要';
var rows = document.querySelectorAll('table tbody tr');

for (var i = 0; i < rows.length; i++) {
  if (rows[i].textContent.indexOf(keyword) !== -1) {
    rows[i].style.backgroundColor = '#fff3cd';
    rows[i].style.fontWeight = 'bold';
  }
}

示例 3:给数据表格添加汇总行

var table = document.querySelector('table tbody');
if (table) {
  var totalRow = document.createElement('tr');
  totalRow.innerHTML = '<td colspan="2"><strong>合计</strong></td><td><strong>3,897.50</strong></td>';
  totalRow.style.backgroundColor = '#f0f0f0';
  table.appendChild(totalRow);
}

示例 4:隐藏指定列

var colIndex = 3;
var cells = document.querySelectorAll('table td:nth-child(' + (colIndex + 1) + '), table th:nth-child(' + (colIndex + 1) + ')');
for (var i = 0; i < cells.length; i++) {
  cells[i].style.display = 'none';
}

示例 5:格式化所有金额为千分位

function formatNumber(num) {
  var parts = num.toString().split('.');
  parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
  return parts.join('.');
}

var priceEls = document.querySelectorAll('.price, .amount, .total');
for (var i = 0; i < priceEls.length; i++) {
  var raw = priceEls[i].textContent.replace(/[,¥$¥]/g, '').trim();
  var num = parseFloat(raw);
  if (!isNaN(num)) {
    priceEls[i].textContent = formatNumber(num);
  }
}

示例 6:动态修改页面主题色

var style = document.createElement('style');
style.textContent = '\
  body { background-color: #1a1a2e !important; color: #e0e0e0 !important; }\
  .card { background-color: #16213e !important; border-color: #0f3460 !important; }\
  .header { background-color: #0f3460 !important; }\
  a { color: #e94560 !important; }\
';
document.head.appendChild(style);

示例 7:给表单自动填充数据 进阶

function fillInput(selector, value) {
  var el = document.querySelector(selector);
  if (!el) return;
  el.value = value;
  el.dispatchEvent(new Event('input', { bubbles: true }));
  el.dispatchEvent(new Event('change', { bubbles: true }));
}

fillInput('#name', '张三');
fillInput('#email', 'zhangsan@example.com');
fillInput('#phone', '13800138000');

示例 8:监控 DOM 变化并自动处理 进阶

var observer = new MutationObserver(function() {
  var items = document.querySelectorAll('.notification-item');
  for (var i = 0; i < items.length; i++) {
    if (items[i].textContent.indexOf('广告') !== -1) {
      items[i].style.display = 'none';
    }
  }
});

observer.observe(document.body, { childList: true, subtree: true });

调试技巧

查看控制台日志

  1. F12 打开浏览器开发者工具
  2. 切换到 Console 标签
  3. MirageX 的日志以 [MirageX] 开头,可以过滤查看

在脚本中使用 console.log

console.log('[我的脚本] 开始执行');
var el = document.querySelector('.price');
console.log('[我的脚本] 找到元素:', el ? el.textContent : '未找到');

检查规则是否生效

在 Console 中输入:

// 查看当前生效的规则
window.__AM && window.__AM.ruleEngine && window.__AM.ruleEngine.getActiveRules()

检查缓存中的规则

// 查看所有已缓存的规则
chrome.storage.local.get('am_rule_cache', function(d) { console.log(d); });

手动清除规则缓存

chrome.storage.local.remove('am_rule_cache', function() { console.log('缓存已清除'); });

常见问题

规则和脚本有什么区别?
规则是声明式的 JSON 配置,适合简单的文本替换和隐藏操作。脚本是完整的 JavaScript 代码,可以做任何 DOM 操作,适合复杂场景。规则更简单安全,脚本更灵活强大。
导入规则需要消耗 AI 点数吗?
是的。每次页面重新打开时应用规则(无论是 AI 生成的还是手动导入的),都会扣除 1 个 AI 点数。这是因为在页面重新加载时,服务端需要验证你的账号状态和权限。但在不关闭页面的情况下,规则会持续生效,切换标签页再回来不会重复扣点。
导入脚本需要消耗 AI 点数吗?
不需要。自定义脚本完全在浏览器本地执行,不经过 AI 服务,不消耗点数。但导入脚本时需要声明脚本修改了几处内容,按修改处数扣点(每处 1 点)。例如脚本修改了 3 个地方的文本,导入时填写 3,扣除 3 个点数。
规则会保存多久?
规则保存在浏览器本地存储(chrome.storage.local)中,除非你手动清除浏览器数据或点击「还原页面」,否则永久有效。
多条规则对同一文本生效时,谁优先?
按数组顺序执行,后面的规则会覆盖前面的。例如先改了金额为 999,再有一条规则改成 888,最终结果是 888。
脚本可以发送网络请求吗?
可以使用 fetchXMLHttpRequest,但受浏览器同源策略限制,只能请求与当前页面同域的 API。跨域请求会被浏览器拦截。
如何删除已导入的脚本?
点击 popup 面板的「还原页面」按钮会停止所有规则和脚本。要永久删除特定脚本,需要清除浏览器本地数据。
为什么脚本执行了但看不到效果?
最常见的原因是脚本执行时目标元素还没有加载完成。使用「延迟执行」模式(在 waitAndExecute 函数中等待元素出现),或将执行间隔设为非 0 值让脚本反复执行。