// ==UserScript==
// @name 智能订单审核
// @namespace http://tampermonkey.net/
// @version 1.1.132
// @description 根据多重条件自动审核大额订单
// @author Cisco
// @match https://7777m.topcms.org/*
// @match https://111bet22.topcms.org/*
// @match https://888bet.topcms.org/*
// @match https://hkgame.topcms.org/*
// @match https://666bet.topcms.org/*
// @match https://k9.topcms.org/*
// @icon https://7777m.topcms.org/favicon.ico
// @license MIT
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_addStyle
// ==/UserScript==
(function () {
"use strict";
// 配置参数
const config = {
currentPage: 1, // 当前页码
totalPages: 1, // 总页数
pageSize: 200, // 每页订单数量
isLastPage: false, // 是否是最后一页
maxWithdrawAmount: 50, // 最大提现金额
betToBonusRatio: 20, // 总投注额/赠送总额最小比率
betToRechargeRatio: 5, // 总投注额/订单充值最小比率
profitToRechargeRatio: 3, // 游戏盈亏/订单充值最大比率
maxSameIPUsers: 2, // 最大相同IP用户数
minBalance: 5, // 最小余额要求
maxWithdrawTimes: 3, // 最大提现次数
password: "", // 充值密码
processedOrders: GM_getValue("processedOrders", {}), // 已处理订单记录
payOutOrders: GM_getValue("payOutOrders", {}), // 已出款订单记录
currentOrderId: null, // 当前处理的订单ID
isProcessing: false, // 是否正在处理中
isReturning: false, // 是否正在返回订单页面
panelCollapsed: false, // 面板是否收起
completedOneRound: false, // 是否完成了一轮处理
processingOrderId: null, // 正在处理的订单ID
totalBetAmount: 0, // 当前订单的总投注额
profitAmount: 0, // 当前订单的游戏盈亏
};
// 添加控制面板样式
GM_addStyle(`
.monitor-panel-order {
position: fixed;
top: 20px;
right: 80px;
z-index: 9999;
background: white;
padding: 15px;
border: 1px solid #ddd;
border-radius: 5px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
font-family: Arial, sans-serif;
width: 320px;
max-height: 90vh;
overflow-y: auto;
transition: all 0.3s ease;
}
.monitor-panel-order.collapsed {
width: 40px;
height: 40px;
overflow: hidden;
padding: 5px;
}
.toggle-panel {
position: absolute;
top: 5px;
right: 5px;
width: 30px;
height: 30px;
border: none;
background: #f0f0f0;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
z-index: 10000;
}
.toggle-panel:hover {
background: #e0e0e0;
}
.collapsed .panel-content {
display: none;
}
.monitor-header {
margin: 0 0 15px 0;
color: #409EFF;
font-size: 16px;
font-weight: bold;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
}
.config-group {
margin-bottom: 12px;
position: relative;
}
.config-label {
display: block;
margin-bottom: 5px;
color: #666;
font-size: 13px;
font-weight: bold;
}
.config-label.required:after {
content: " *";
color: #F56C6C;
}
.config-input {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
.config-input.error {
border-color: #F56C6C;
}
.error-message {
color: #F56C6C;
font-size: 12px;
margin-top: 3px;
display: none;
}
.monitor-button {
width: 100%;
padding: 10px;
background: #409EFF;
color: white;
border: none;
border-radius: 4px;
font-weight: bold;
cursor: pointer;
transition: background 0.3s;
margin-bottom: 10px;
}
.monitor-button:disabled {
background: #C0C4CC;
cursor: not-allowed;
}
.monitor-button.stop {
background: #F56C6C;
}
.monitor-stats {
margin-top: 15px;
font-size: 12px;
color: #666;
border-top: 1px solid #eee;
padding-top: 10px;
}
.monitor-stat-row {
display: flex;
justify-content: space-between;
margin-bottom: 5px;
}
.monitor-progress-container {
margin: 10px 0;
height: 10px;
background: #f0f0f0;
border-radius: 5px;
overflow: hidden;
}
.monitor-progress-bar {
height: 100%;
background: linear-gradient(to right, #67C23A, #409EFF);
transition: width 0.3s;
}
#statusText {
font-weight: bold;
color: #409EFF;
}
#processedCount {
font-weight: bold;
color: #67C23A;
}
.button-container {
display: flex;
flex-direction: column;
}
.monitor-button.hidden {
display: none;
}
`);
// 验证输入参数
function validateInputs() {
let isValid = true;
const inputs = [
{ id: "maxAmount", name: "最大提现金额" },
{ id: "betBonusRatio", name: "总投注额大于赠送总额指定倍数" },
{ id: "betRechargeRatio", name: "总投注额大于订单充值指定倍数" },
{ id: "profitRatio", name: "游戏盈亏小于订单充值指定倍数" },
{ id: "maxSameIPUsers", name: "最大相同IP用户数" },
{ id: "minBalance", name: "最小余额要求" },
{ id: "maxWithdrawTimes", name: "最大提现次数" },
{ id: "withdrawPassword", name: "充值密码" },
];
inputs.forEach((input) => {
const element = document.getElementById(input.id);
const errorElement =
element.parentElement.querySelector(".error-message") ||
createErrorElement(element.parentElement);
if (input.id === "withdrawPassword") {
if (!element.value.trim()) {
element.classList.add("error");
errorElement.textContent = `${input.name}不能为空`;
errorElement.style.display = "block";
isValid = false;
} else {
element.classList.remove("error");
errorElement.style.display = "none";
}
} else {
if (!element.value.trim()) {
element.classList.add("error");
errorElement.textContent = `${input.name}不能为空`;
errorElement.style.display = "block";
isValid = false;
} else if (isNaN(element.value)) {
element.classList.add("error");
errorElement.textContent = `${input.name}必须是数字`;
errorElement.style.display = "block";
isValid = false;
} else {
element.classList.remove("error");
errorElement.style.display = "none";
}
}
});
return isValid;
}
// 创建错误提示元素
function createErrorElement(parent) {
const errorElement = document.createElement("div");
errorElement.className = "error-message";
parent.appendChild(errorElement);
return errorElement;
}
// 更新按钮显示状态
function updateButtonVisibility() {
const startBtn = document.getElementById("startBtn");
const stopBtn = document.getElementById("stopBtn");
if (config.isProcessing) {
startBtn.classList.add("hidden");
stopBtn.classList.remove("hidden");
} else {
startBtn.classList.remove("hidden");
stopBtn.classList.add("hidden");
}
}
// 添加控制面板
function addControlPanel() {
const panel = document.createElement("div");
panel.className = "monitor-panel-order";
panel.id = "autoWithdrawPanel";
// 添加收起/展开按钮
const toggleBtn = document.createElement("button");
toggleBtn.className = "toggle-panel";
toggleBtn.innerHTML = "×";
toggleBtn.title = "收起/展开控制面板";
toggleBtn.addEventListener("click", togglePanel);
// 面板内容
const panelContent = document.createElement("div");
panelContent.className = "panel-content";
panelContent.innerHTML = `
<h3 class="monitor-header">智能自动出款系统</h3>
<div class="config-group">
<label class="config-label required">最大提现金额</label>
<input type="number" class="config-input" id="maxAmount" value="${
config.maxWithdrawAmount
}" required>
<div class="error-message"></div>
</div>
<div class="config-group">
<label class="config-label required">总投注额大于赠送总额指定倍数</label>
<input type="number" class="config-input" id="betBonusRatio" value="${
config.betToBonusRatio
}" step="0.1" required>
<div class="error-message"></div>
</div>
<div class="config-group">
<label class="config-label required">总投注额大于订单充值指定倍数</label>
<input type="number" class="config-input" id="betRechargeRatio" value="${
config.betToRechargeRatio
}" step="0.1" required>
<div class="error-message"></div>
</div>
<div class="config-group">
<label class="config-label required">游戏盈亏小于订单充值指定倍数</label>
<input type="number" class="config-input" id="profitRatio" value="${
config.profitToRechargeRatio
}" step="0.1" required>
<div class="error-message"></div>
</div>
<div class="config-group">
<label class="config-label required">最大相同IP用户数</label>
<input type="number" class="config-input" id="maxSameIPUsers" value="${
config.maxSameIPUsers
}" required>
<div class="error-message"></div>
</div>
<div class="config-group">
<label class="config-label required">最小余额要求</label>
<input type="number" class="config-input" id="minBalance" value="${
config.minBalance
}" required>
<div class="error-message"></div>
</div>
<div class="config-group">
<label class="config-label required">最大提现次数</label>
<input type="number" class="config-input" id="maxWithdrawTimes" value="${
config.maxWithdrawTimes
}" required>
<div class="error-message"></div>
</div>
<div class="config-group">
<label class="config-label required">充值密码</label>
<input type="text" class="config-input" id="withdrawPassword" value="${
config.password
}" required>
<div class="error-message"></div>
</div>
<div class="button-container">
<button id="startBtn" class="monitor-button ${
config.isProcessing ? "hidden" : ""
}">开始处理</button>
<button id="stopBtn" class="monitor-button stop ${
!config.isProcessing ? "hidden" : ""
}">停止处理</button>
</div>
<div class="button-container">
<button id="clearCacheBtn" class="monitor-button">清理缓存</button>
</div>
<div class="monitor-stats">
<div class="monitor-stat-row">
<span>状态:</span>
<span id="statusText">待命</span>
</div>
<div class="monitor-stat-row">
<span>已处理:</span>
<span id="processedCount">${
Object.keys(config.processedOrders).length
}</span> 单
</div>
<div class="monitor-stat-row">
<span>已出款:</span>
<span id="payOutOrders">${Object.keys(
config.payOutOrders
).join(", ")}</span>
</div>
</div>
`;
panel.appendChild(toggleBtn);
panel.appendChild(panelContent);
document.body.appendChild(panel);
// 恢复面板状态
config.panelCollapsed = GM_getValue("panelCollapsed", false);
if (config.panelCollapsed) {
panel.classList.add("collapsed");
toggleBtn.innerHTML = "≡";
}
// 事件监听
document.getElementById("startBtn").addEventListener("click", function () {
if (validateInputs()) {
startProcessing();
}
});
document
.getElementById("stopBtn")
.addEventListener("click", stopProcessing);
// 为所有输入框添加实时验证
document.querySelectorAll(".config-input").forEach((input) => {
input.addEventListener("input", function () {
validateInputs();
});
});
// 绑定清理缓存事件
document
.getElementById("clearCacheBtn")
.addEventListener("click", function () {
if (confirm("确定要清理缓存数据吗?这会清空已处理订单记录。")) {
// 清空内存中的数据
config.processedOrders = {};
config.payOutOrders = {};
// 清空本地存储
GM_setValue("processedOrders", {});
GM_setValue("payOutOrders", {});
// 更新计数和显示
document.getElementById("processedCount").textContent = "0";
document.getElementById("payOutOrders").textContent = "";
updateStatus("缓存已清理");
}
});
}
// 收起/展开面板
function togglePanel() {
const panel = document.getElementById("autoWithdrawPanel");
config.panelCollapsed = !panel.classList.contains("collapsed");
if (config.panelCollapsed) {
panel.classList.add("collapsed");
this.innerHTML = "≡";
} else {
panel.classList.remove("collapsed");
this.innerHTML = "×";
}
GM_setValue("panelCollapsed", config.panelCollapsed);
}
async function setPageSizeFast(targetSize = 200) {
const pagination = document.querySelector('.el-pagination');
if (!pagination) throw new Error('未找到分页组件');
const sizeInput = pagination.querySelector('.el-select .el-input');
if (!sizeInput) throw new Error('未找到下拉输入框');
// 打开下拉菜单
sizeInput.click();
// 等待下拉项出现
const item = await waitForDropdownItem(targetSize);
if (!item) throw new Error(`未找到 ${targetSize} 条/页 选项`);
item.click();
console.log(`✅ 成功切换到每页 ${targetSize} 条`);
}
// 等待指定分页选项出现
function waitForDropdownItem(size, maxTries = 10) {
return new Promise((resolve) => {
let tries = 0;
function check() {
const items = document.querySelectorAll('.el-select-dropdown__item span');
const match = Array.from(items).find(span => span.textContent.includes(size + '条'));
if (match) return resolve(match.parentElement);
if (++tries >= maxTries) return resolve(null);
requestAnimationFrame(check);
}
check();
});
}
// 获取分页信息
function updatePaginationInfo() {
const pagination = document.querySelector(".el-pagination");
if (!pagination) {
console.error("无法找到分页元素");
// 默认值
config.currentPage = 1;
config.totalPages = 1;
config.isLastPage = true;
return;
}
// 当前页
const activePage = pagination.querySelector(".el-pager .number.active");
config.currentPage = activePage ? parseInt(activePage.textContent) : 1;
// 每页数量
const pageSizeSelect = pagination.querySelector(
".el-select-dropdown__item.selected"
);
config.pageSize = pageSizeSelect
? parseInt(pageSizeSelect.textContent)
: null;
// 总条数
let totalItems = null;
const totalTextEl = pagination.querySelector(".el-pagination__total");
if (totalTextEl) {
const totalMatch = totalTextEl.textContent.match(/共\s*(\d+)\s*条/);
if (totalMatch) {
totalItems = parseInt(totalMatch[1]);
}
}
// 计算总页数
if (totalItems !== null && config.pageSize) {
config.totalPages = Math.ceil(totalItems / config.pageSize);
} else {
// 如果没法算,用当前页作为总页数兜底
config.totalPages = config.currentPage || 1;
}
// 是否最后一页
const nextBtn = pagination.querySelector(".btn-next");
if (config.totalPages === 1) {
config.isLastPage = true; // 只有一页直接是最后一页
} else if (nextBtn) {
config.isLastPage = nextBtn.disabled;
} else {
// 没有下一页按钮时,如果当前页是总页数,也认为是最后一页
config.isLastPage = config.currentPage >= config.totalPages;
}
console.log(
`当前页码: ${config.currentPage}/${config.totalPages}`,
`每页: ${config.pageSize || "-"}条`,
`是否末页: ${config.isLastPage}`
);
}
// 跳转到最后一页
function goToLastPage() {
const pageInput = document.querySelector(".el-pagination__editor input");
const jumpBtn = document.querySelector(".el-pagination__jump");
if (pageInput && jumpBtn) {
// 设置页码为总页数
const setter = Object.getOwnPropertyDescriptor(
HTMLInputElement.prototype,
"value"
).set;
setter.call(pageInput, config.totalPages);
pageInput.dispatchEvent(new Event("input", { bubbles: true }));
pageInput.dispatchEvent(new Event("change", { bubbles: true }));
// 模拟回车键触发跳转
setTimeout(() => {
const enterEvent = new KeyboardEvent("keydown", {
key: "Enter",
code: "Enter",
keyCode: 13,
which: 13,
bubbles: true,
});
pageInput.dispatchEvent(enterEvent);
// 等待页面加载
setTimeout(processOrderPage, 2000);
}, 500);
} else {
console.error("无法找到分页跳转控件");
setTimeout(processOrderPage, 3000);
}
}
// 跳转到上一页
function goToPrevPage() {
const prevBtn = document.querySelector(
".el-pagination .btn-prev:not([disabled])"
);
if (prevBtn) {
prevBtn.click();
setTimeout(() => {
config.currentPage--;
processOrderPage();
}, 2000);
} else {
updateStatus("已是第一页,处理完成");
setTimeout(processOrderPage, 5000);
}
}
// 开始处理
function startProcessing() {
if (config.isProcessing) return;
// 更新配置
updateConfig();
config.isProcessing = true;
updateStatus("开始处理订单...");
updateButtonVisibility();
// 检查当前页面
if (isOrderPage()) {
processOrderPage();
} else if (isAgentPage()) {
processAgentPage();
} else {
// 不在目标页面,跳转到订单页面
updateStatus("正在跳转到订单页面...");
window.location.href = "#/order/unread-withdraw";
}
}
// 停止处理
function stopProcessing() {
config.isProcessing = false;
config.processingOrderId = null;
updateStatus("处理已停止");
updateButtonVisibility();
}
// 更新配置
function updateConfig() {
config.maxWithdrawAmount = parseFloat(
document.getElementById("maxAmount").value
);
config.betToBonusRatio = parseFloat(
document.getElementById("betBonusRatio").value
);
config.betToRechargeRatio = parseFloat(
document.getElementById("betRechargeRatio").value
);
config.profitToRechargeRatio = parseFloat(
document.getElementById("profitRatio").value
);
config.maxSameIPUsers = parseInt(
document.getElementById("maxSameIPUsers").value
);
config.minBalance = parseFloat(document.getElementById("minBalance").value);
config.maxWithdrawTimes = parseInt(
document.getElementById("maxWithdrawTimes").value
);
config.password = document.getElementById("withdrawPassword").value;
}
// 更新状态
function updateStatus(text) {
const statusEl = document.getElementById("statusText");
if (statusEl) {
statusEl.textContent = text;
}
}
// 检查是否在订单页面
function isOrderPage() {
return window.location.hash.includes("#/order/unread-withdraw");
}
// 检查是否在代理页面
function isAgentPage() {
return window.location.hash.includes("#/agent/agent-list");
}
// 点击查询按钮的函数
function clickSearchButton() {
// 获取所有filter-container元素
const filterContainers = document.querySelectorAll(".filter-container");
// 第三个filter-container包含查询按钮
if (filterContainers.length >= 3) {
const searchContainer = filterContainers[2];
// 查找查询按钮 - 确保不是禁用状态且文本是"查询"
const searchBtn = Array.from(
searchContainer.querySelectorAll("button.el-button")
).find((btn) => !btn.disabled && btn.textContent.includes("查询"));
if (searchBtn) {
updateStatus("点击查询按钮重新开始处理...");
// 先清空所有搜索条件
clearAllSearchInputs();
// 点击查询按钮
searchBtn.click();
// 等待查询完成
setTimeout(() => {
config.processedOrders = {};
GM_setValue("processedOrders", {});
document.getElementById("processedCount").textContent = "0";
config.completedOneRound = false;
GM_setValue("completedOneRound", false);
// 重新开始处理
setTimeout(processOrderPage, 500);
}, 1000);
return;
}
}
// 如果没找到按钮,尝试其他方式
updateStatus("未找到查询按钮,3秒后尝试重新开始");
setTimeout(processOrderPage, 3000);
}
// 清空所有搜索输入框的函数
function clearAllSearchInputs() {
// 清空订单号输入框
const orderInput = document.querySelector(
'.filter-container input[placeholder="请输入订单号"]'
);
if (orderInput) {
orderInput.value = "";
orderInput.dispatchEvent(new Event("input", { bubbles: true }));
}
// 清空用户ID输入框
const userIdInput = document.querySelector(
'.filter-container input[placeholder="请输入用户ID"]'
);
if (userIdInput) {
userIdInput.value = "";
userIdInput.dispatchEvent(new Event("input", { bubbles: true }));
}
// 重置第三方选择器
const thirdPartySelect = document.querySelector(
'.el-select input[placeholder="全部"]'
);
if (thirdPartySelect && thirdPartySelect.value !== "全部") {
thirdPartySelect.value = "全部";
thirdPartySelect.dispatchEvent(new Event("input", { bubbles: true }));
}
// 清空日期范围选择器
const dateInputs = document.querySelectorAll(".el-range-input");
dateInputs.forEach((input) => {
if (input.value) {
input.value = "";
input.dispatchEvent(new Event("input", { bubbles: true }));
}
});
}
// 处理订单页面
async function processOrderPage() {
try {
if (!config.isProcessing) return;
if (config.processingOrderId) {
// 不再反复打印日志
return setTimeout(processOrderPage, 1000);
}
await setPageSizeFast(200);
// 获取分页信息
updatePaginationInfo();
// 如果不是最后一页,先跳转到最后一页
if (!config.isLastPage && config.currentPage < config.totalPages) {
return goToLastPage();
}
const rows = document.querySelectorAll(
".el-table--scrollable-x .el-table__body .el-table__row"
);
if (rows.length === 0) {
if (config.currentPage > 1) {
goToPrevPage();
} else {
updateStatus("所有订单已处理完成");
// 记录已完成一轮处理
config.completedOneRound = true;
GM_setValue("completedOneRound", true);
// 5秒后点击查询按钮
setTimeout(() => {
clickSearchButton();
}, 5000);
}
return;
}
// 从最后一行开始处理
for (let i = rows.length - 1; i >= 0; i--) {
const row = rows[i];
const orderId = getOrderIdFromRow(row);
console.log("订单号:", orderId);
// 跳过已处理的订单
if (config.processedOrders[orderId]) {
console.log(`[跳过] 订单 ${orderId} 已处理`);
continue;
}
config.processingOrderId = orderId; // 设置当前处理中的订单ID
console.log(`[处理中] 页码 ${config.currentPage} 的订单 ${orderId}`);
// 1.1 检查提现金额
const amountNode = row.querySelector("td:nth-child(8) .cell > span"); // 第8列通常是金额列
if (!amountNode) {
// 如果第8列找不到,尝试其他可能的位置
const amountNodes = row.querySelectorAll("td .cell > span");
let foundAmount = false;
for (const node of amountNodes) {
// 检查是否是金额(包含数字和小数点)
if (/^\d+\.\d{2}$/.test(node.textContent.trim())) {
amountNode = node;
foundAmount = true;
break;
}
}
if (!foundAmount) {
console.error("提取提现金额失败", row);
markOrderAsProcessed(orderId, "格式错误");
continue;
}
}
const amount = parseFloat(amountNode.textContent);
if (amount > config.maxWithdrawAmount) {
console.log(`[跳过] 金额 ${amount} 超过限制`);
markOrderAsProcessed(orderId, "金额超限");
continue;
}
// 1.2-1.4 检查用户详情
// 使用更稳定的选择器定位用户名元素
const usernameEl = row.querySelector("td:nth-child(2) .el-tooltip"); // 用户名通常在第二列
if (!usernameEl) {
// 如果第二列找不到,尝试其他方式
const usernameEls = row.querySelectorAll(".el-tooltip");
if (usernameEls.length > 0) {
usernameEl = usernameEls[0]; // 取第一个el-tooltip元素
} else {
console.error("找不到用户名元素", row);
markOrderAsProcessed(orderId, "格式错误");
continue;
}
}
config.currentOrderId = orderId;
config.currentProcessingRow = i; // 记录当前处理的行索引
usernameEl.click();
// 等待弹窗出现
setTimeout(checkUserDetail, 1500);
return; // 等待异步处理
}
// 当前页处理完成,跳转上一页
if (config.currentPage > 1) {
goToPrevPage();
} else {
updateStatus("已完成所有订单处理");
// 记录已完成一轮处理
config.completedOneRound = true;
GM_setValue("completedOneRound", true);
// 5秒后点击查询按钮
setTimeout(() => {
clickSearchButton();
}, 5000);
}
} catch (e) {
console.error("processOrderPage 异常:", e);
config.processingOrderId = null;
setTimeout(processOrderPage, 1000);
}
}
// 检查用户详情弹窗
function checkUserDetail() {
// 如果当前没有在处理订单,则直接返回
if (!config.isProcessing) {
updateStatus("等待处理订单...");
return;
}
// 查找当前显示的用户详情弹窗
const dialog = document.querySelector(
'.el-dialog__wrapper:not([style*="display: none"])'
);
if (!dialog) {
updateStatus("等待用户详情弹窗...");
// 1.5秒后重试
setTimeout(checkUserDetail, 1500);
return;
}
// 获取弹窗中的所有表格
const tables = dialog.querySelectorAll(".el-table");
// 第二个表格包含所需的财务数据(余额、投注额、充值等)
const financialTable = tables[1];
if (!financialTable) {
closeDialogAndContinue();
return;
}
// 获取财务表格中的所有数据单元格
const cells = financialTable.querySelectorAll(
".el-table__body .cell > span"
);
// 按固定位置提取数值(索引从0开始)
// 列顺序:余额, 误差, 订单充值, 订单提现, 提现手续费, 公积金购买, 通行证购买, 充提差, 游戏盈亏, 总投注额, 总打码量, 赠送总额
const balanceText = cells[0]?.textContent || "0"; // 余额
const totalRechargeText = cells[2]?.textContent || "0"; // 订单充值
const profitText = cells[8]?.textContent || "0"; // 游戏盈亏
const totalBetText = cells[9]?.textContent || "0"; // 总投注额
const totalBonusText = cells[11]?.textContent || "0"; // 赠送总额
// 第三个表格包含相同IP用户数
const sameIPTable = tables[2];
const sameIPUsersText =
sameIPTable?.querySelector(".el-table__body .cell > span")?.textContent ||
"0";
// 数值解析函数
const parseValue = (text) => {
// 移除所有非数字字符(保留小数点和负号)
const numStr = text.replace(/[^\d.-]/g, "");
return parseFloat(numStr) || 0;
};
// 解析各数值
const totalBet = parseValue(totalBetText); // 总投注额
const totalBonus = parseValue(totalBonusText); // 赠送总额
const totalRecharge = parseValue(totalRechargeText); // 订单充值
const profit = parseValue(profitText); // 游戏盈亏
const sameIPUsers = parseInt(sameIPUsersText) || 0; // 相同IP用户数
const balance = parseValue(balanceText); // 余额
config.totalBetAmount = totalBet; // 记录当前订单的总投注额
config.profitAmount = profit; // 记录当前订单的游戏盈亏
console.log("总投注额:", totalBet);
console.log("赠送总额:", totalBonus);
console.log("订单充值:", totalRecharge);
console.log("游戏盈亏:", profit);
console.log("相同IP用户数:", sameIPUsers);
console.log("余额:", balance);
// 1.2 检查总投注额 > 赠送总额 × 指定倍数
if (totalBet <= totalBonus * config.betToBonusRatio) {
updateStatus(
`订单 ${config.currentOrderId} 投注额不满足大于赠送额指定倍数条件`
);
markOrderAsProcessed(config.currentOrderId, "不满足条件");
closeDialogAndContinue();
return;
}
// 1.3 检查总投注额 > 订单充值 × 指定倍数
if (totalBet <= totalRecharge * config.betToRechargeRatio) {
config.processingOrderId = null;
updateStatus(
`订单 ${config.currentOrderId} 投注额不满足大于充值额指定倍数条件`
);
markOrderAsProcessed(config.currentOrderId, "不满足条件");
closeDialogAndContinue();
return;
}
// 1.4 检查游戏盈亏绝对值 < 订单充值 × 指定倍数
if (Math.abs(profit) > totalRecharge * config.profitToRechargeRatio) {
updateStatus(
`订单 ${config.currentOrderId} 盈亏不满足小于充值额指定倍数条件`
);
markOrderAsProcessed(config.currentOrderId, "不满足条件");
closeDialogAndContinue();
return;
}
// 检查相同IP用户数是否超过限制
if (sameIPUsers > config.maxSameIPUsers) {
updateStatus(`订单 ${config.currentOrderId} 相同IP用户数超过限制`);
markOrderAsProcessed(config.currentOrderId, "相同IP用户数超限");
closeDialogAndContinue();
return;
}
// 检查用户余额是否满足最低要求
if (balance < config.minBalance) {
updateStatus(
`订单 ${config.currentOrderId} 余额不足 (${balance} < ${config.minBalance})`
);
markOrderAsProcessed(config.currentOrderId, "余额不足");
closeDialogAndContinue();
return;
}
// 从用户信息区域提取用户ID
const userIdEl = dialog.querySelector(
".el-table__row .cell div div:nth-child(3)"
);
const userId = userIdEl
? userIdEl.textContent.replace("ID:", "").trim()
: null;
config.currentUserId = userId;
console.log("用户ID:", userId);
// 关闭当前弹窗
closeDialog();
// 所有条件满足,跳转到提现订单页面进行下一步检查
updateStatus(
`订单 ${config.currentOrderId} 用户 ${userId} 满足条件,检查提现记录...`
);
setTimeout(() => {
window.location.href = "#/order/order-withdraw";
}, 1000);
}
// 从弹窗中提取用户ID
function findUserIdFromDialog(dialog) {
if (!dialog) return null;
const divs = dialog.querySelectorAll("div");
for (const div of divs) {
const text = div.textContent?.trim();
if (text?.startsWith("ID:")) {
return text.replace("ID:", "").trim();
}
}
return null;
}
// 处理提现订单页面
function processWithdrawOrderPage() {
if (!config.isProcessing) return;
console.log("正在处理提现订单页面,用户ID:", config.currentUserId);
let retryCount = 0;
const maxRetries = 5;
const retryInterval = 1000;
const tryProcess = () => {
retryCount++;
console.log(`尝试处理提现订单页面 (第 ${retryCount} 次)`);
// 1. 查找用户ID输入框 - 根据提供的HTML结构调整选择器
const idInput = document.querySelector(
'input[placeholder="请输入用户ID"].el-input__inner'
);
if (!idInput) {
if (retryCount < maxRetries) {
console.log("未找到用户ID输入框,等待重试...");
setTimeout(tryProcess, retryInterval);
return;
} else {
console.error("多次重试后仍未找到用户ID输入框");
return;
}
}
// 2. 设置用户ID值
try {
// 更可靠的值设置方式
idInput.focus();
idInput.value = "";
// 使用原生方法设置值
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
HTMLInputElement.prototype,
"value"
).set;
nativeInputValueSetter.call(idInput, config.currentUserId);
// 触发所有必要事件
["input", "change", "blur"].forEach((eventType) => {
idInput.dispatchEvent(new Event(eventType, { bubbles: true }));
});
console.log("已设置用户ID:", config.currentUserId);
// 3. 调整日期范围
setTimeout(() => {
adjustDateTimeRange();
// 查找下拉菜单容器(可能在body的末尾)
const dropdown = document.querySelectorAll(
".el-select-dropdown.el-popper"
);
if (!dropdown) {
console.error("找不到下拉菜单");
returnToOrderPage();
return;
}
const payItems = dropdown[0]; // 取第一个
// 查找已支付选项
const items = payItems.querySelectorAll(".el-select-dropdown__item");
let payItem = null;
for (const item of items) {
if (item.textContent.trim().toLowerCase() === "已支付") {
payItem = item;
break;
}
}
if (!payItem) {
console.error("找不到已支付选项");
// 没有已支付选项,继续代理检查
updateStatus(
`用户 ${config.currentUserId} 无充值记录,返回订单列表`
);
setTimeout(() => {
processOrderPage();
}, 1000);
return;
}
// 选择已支付选项
payItem.click();
// 4. 查找并点击查询按钮 - 根据提供的HTML结构调整选择器
const queryBtn = Array.from(
document.querySelectorAll(".filter-container button.el-button")
).find((btn) => {
const span = btn.querySelector("span");
return span && span.textContent.trim() === "查询";
});
if (queryBtn) {
console.log("找到查询按钮,正在点击...");
queryBtn.click();
setTimeout(checkWithdrawTimes, 2000);
} else {
console.error("未找到查询按钮");
setTimeout(checkWithdrawTimes, 1000);
}
}, 300);
} catch (error) {
console.error("设置用户ID时出错:", error);
if (retryCount < maxRetries) {
setTimeout(tryProcess, retryInterval);
}
}
};
// 初始尝试
setTimeout(tryProcess, 1500); // 给页面一点加载时间
}
// 调整日期时间范围(减8小时)
function adjustDateTimeRange() {
// 找到日期范围输入框
const dateRangeInputs = document.querySelectorAll(".el-range-input");
if (dateRangeInputs.length < 2) {
console.error("找不到日期范围输入框");
return;
}
const startInput = dateRangeInputs[0];
const endInput = dateRangeInputs[1];
// 获取当前日期时间
const now = new Date();
const endDate = new Date(
now.getFullYear(),
now.getMonth(),
now.getDate(),
23,
59,
59
);
const startDate = new Date(
now.getFullYear(),
now.getMonth(),
now.getDate(),
0,
0,
0
);
// 减8小时
startDate.setHours(startDate.getHours() - 8);
endDate.setHours(endDate.getHours() - 8);
// 格式化日期时间
const formatDate = (date) => {
const pad = (num) => num.toString().padStart(2, "0");
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(
date.getDate()
)} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(
date.getSeconds()
)}`;
};
// 设置日期时间
const setter = Object.getOwnPropertyDescriptor(
HTMLInputElement.prototype,
"value"
).set;
setter.call(startInput, formatDate(startDate));
startInput.dispatchEvent(new Event("input", { bubbles: true }));
setter.call(endInput, formatDate(endDate));
endInput.dispatchEvent(new Event("input", { bubbles: true }));
console.log(
"已调整日期时间范围:",
formatDate(startDate),
"至",
formatDate(endDate)
);
}
// 调整日期时间范围(7天内减8小时)
function adjustDateTimeRange7d() {
// 找到日期范围输入框
const dateRangeInputs = document.querySelectorAll(".el-range-input");
if (dateRangeInputs.length < 2) {
console.error("找不到日期范围输入框");
return;
}
const startInput = dateRangeInputs[0];
const endInput = dateRangeInputs[1];
// 获取当前日期时间
const now = new Date();
const endDate = new Date(
now.getFullYear(),
now.getMonth(),
now.getDate(),
23,
59,
59
);
const startDate = new Date(
now.getFullYear(),
now.getMonth(),
now.getDate(),
0,
0,
0
);
// 减8小时
startDate.setDate(startDate.getDate() - 6);
startDate.setHours(startDate.getHours() - 8);
endDate.setHours(endDate.getHours() - 8);
// 格式化日期时间
const formatDate = (date) => {
const pad = (num) => num.toString().padStart(2, "0");
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(
date.getDate()
)} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(
date.getSeconds()
)}`;
};
// 设置日期时间
const setter = Object.getOwnPropertyDescriptor(
HTMLInputElement.prototype,
"value"
).set;
setter.call(startInput, formatDate(startDate));
startInput.dispatchEvent(new Event("input", { bubbles: true }));
setter.call(endInput, formatDate(endDate));
endInput.dispatchEvent(new Event("input", { bubbles: true }));
console.log(
"已调整日期时间范围:",
formatDate(startDate),
"至",
formatDate(endDate)
);
}
// 处理充值订单页面
function processTopupOrderPage() {
if (!config.isProcessing) return;
console.log("正在处理充值订单页面,用户ID:", config.currentUserId);
let retryCount = 0;
const maxRetries = 5;
const retryInterval = 1000;
const tryProcess = () => {
retryCount++;
console.log(`尝试处理充值订单页面 (第 ${retryCount} 次)`);
// 1. 查找用户ID输入框
const idInput = document.querySelector(
'input[placeholder="请输入用户ID"].el-input__inner'
);
if (!idInput) {
if (retryCount < maxRetries) {
console.log("未找到用户ID输入框,等待重试...");
setTimeout(tryProcess, retryInterval);
return;
} else {
console.error("多次重试后仍未找到用户ID输入框");
markOrderAsProcessed(config.currentOrderId, "获取充值记录失败");
returnToOrderPage();
return;
}
}
// 2. 设置用户ID值
try {
// 清空并设置用户ID
idInput.focus();
idInput.value = "";
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
HTMLInputElement.prototype,
"value"
).set;
nativeInputValueSetter.call(idInput, config.currentUserId);
// 触发事件
["input", "change", "blur"].forEach((eventType) => {
idInput.dispatchEvent(new Event(eventType, { bubbles: true }));
});
console.log("已设置用户ID:", config.currentUserId);
// 找到订单状态下拉选择框
const orderStatusSelect = document.querySelector(
'.el-select input[placeholder="全部状态"]'
);
if (!orderStatusSelect) {
console.error("找不到订单状态下拉选择框");
setTimeout(() => {
processTopupOrderPage();
}, 1000);
return;
}
// 3. 设置订单状态为"已支付"
setTimeout(() => {
// 查找下拉菜单容器(可能在body的末尾)
const dropdown = document.querySelectorAll(
".el-select-dropdown.el-popper"
);
if (!dropdown) {
console.error("找不到下拉菜单");
returnToOrderPage();
return;
}
const payItems = dropdown[0]; // 取第一个
// 查找已支付选项
const items = payItems.querySelectorAll(".el-select-dropdown__item");
let payItem = null;
for (const item of items) {
if (item.textContent.trim().toLowerCase() === "已支付") {
payItem = item;
break;
}
}
if (!payItem) {
console.error("找不到已支付选项");
// 没有已支付选项,继续代理检查
updateStatus(
`用户 ${config.currentUserId} 无充值记录,返回订单列表`
);
setTimeout(() => {
processOrderPage();
}, 1000);
return;
}
// 选择已支付选项
payItem.click();
// 点击查询按钮
setTimeout(() => {
const queryBtn = Array.from(
document.querySelectorAll(".filter-container button.el-button")
).find((btn) => {
const span = btn.querySelector("span");
return span && span.textContent.trim() === "查询";
});
if (queryBtn) {
console.log("找到查询按钮,正在点击...");
queryBtn.click();
// 检查查询结果
setTimeout(() => {
checkRechargeResult();
}, 2000);
} else {
console.error("未找到查询按钮");
markOrderAsProcessed(config.currentOrderId, "获取充值记录失败");
returnToOrderPage();
}
}, 500);
}, 800);
} catch (error) {
console.error("设置用户ID时出错:", error);
if (retryCount < maxRetries) {
setTimeout(tryProcess, retryInterval);
} else {
markOrderAsProcessed(config.currentOrderId, "获取充值记录失败");
returnToOrderPage();
}
}
};
setTimeout(tryProcess, 1500);
}
// 检查充值结果并获取充值金额
function checkRechargeResult() {
console.log("正在检查充值记录...");
// 1. 检查是否显示“暂无数据”
const emptyText = document.querySelector(".el-table__empty-text");
if (emptyText && emptyText.textContent.includes("暂无数据")) {
console.log("没有充值记录");
markOrderAsProcessed(config.currentOrderId, "无充值记录");
setTimeout(() => {
window.location.href = "#/order/unread-withdraw";
}, 1000);
return;
}
// 2. 获取充值记录表格的所有行
const rows = document.querySelectorAll(".el-table__body .el-table__row");
console.log("找到的充值记录行数:", rows.length);
if (rows.length === 0) {
console.log("没有充值记录");
markOrderAsProcessed(config.currentOrderId, "无充值记录");
setTimeout(() => {
window.location.href = "#/order/unread-withdraw";
}, 1000);
return;
}
// 3. 取最新的一条记录,这里用第二行,因为第一行是统计数据
const latestRow = rows[1];
console.log("最新的充值记录:", latestRow);
// 4. 从该行中获取所有单元格
const cells = latestRow.querySelectorAll("td");
// 5. 充值金额在第9列(从1开始计数),索引为8
const amountCell = cells[8]?.querySelector(".cell > span");
if (!amountCell) {
console.error("找不到充值金额单元格");
markOrderAsProcessed(config.currentOrderId, "获取充值金额失败");
setTimeout(() => {
window.location.href = "#/order/unread-withdraw";
}, 1000);
return;
}
// 6. 提取充值金额文本并转换为浮点数
const rechargeAmount =
parseFloat(amountCell.textContent.replace(/[^\d.-]/g, "")) || 0;
console.log("获取到的充值金额:", rechargeAmount);
console.log("当前订单的游戏盈亏:", config.profitAmount);
// 1.3 检查总投注额 > 订单充值 × 指定倍数
if (config.totalBetAmount <= totalRecharge * config.betToRechargeRatio) {
config.processingOrderId = null;
updateStatus(
`订单 ${config.currentOrderId} 投注额不满足大于最新充值额指定倍数条件`
);
markOrderAsProcessed(config.currentOrderId, "不满足条件");
setTimeout(() => {
window.location.href = "#/order/unread-withdraw";
}, 1000);
return;
}
// 7. 判断盈亏是否满足要求(盈亏绝对值 < 充值金额 × 指定倍数)
if (
Math.abs(config.profitAmount) >
rechargeAmount * config.profitToRechargeRatio
) {
config.processingOrderId = null;
updateStatus(
`订单 ${config.currentOrderId} 盈亏不满足小于最新充值额指定倍数条件`
);
markOrderAsProcessed(config.currentOrderId, "不满足条件");
setTimeout(() => {
window.location.href = "#/order/unread-withdraw";
}, 1000);
return;
}
// 8. 盈亏条件满足,跳转提现页面继续检查
updateStatus(
`用户 ${config.currentUserId} 游戏盈亏满足条件,继续检查提现次数`
);
setTimeout(() => {
window.location.href = "#/order/order-withdraw";
}, 1000);
}
// 检查提现次数
function checkWithdrawTimes() {
console.log("正在检查提现次数...");
// 1. 检查是否有"暂无数据"提示
const emptyText = document.querySelector(".el-table__empty-text");
if (emptyText && emptyText.textContent.includes("暂无数据")) {
console.log("没有提现记录");
checkCoinPayWithdraw();
return;
}
// 2. 获取表格的所有行
const rows = document.querySelectorAll(".el-table__body .el-table__row");
if (rows.length <= 1) {
// 只有统计行,没有实际数据
console.log("没有实际提现记录");
checkCoinPayWithdraw();
return;
}
// 3. 计算当天的 GMT+0 日期
// 系统时间默认是 GMT+8,所以减去 8 小时得到 GMT+0
const now = new Date();
now.setHours(now.getHours() - 8);
const todayGMT0Year = now.getUTCFullYear();
const todayGMT0Month = now.getUTCMonth();
const todayGMT0Date = now.getUTCDate();
let todayCount = 0;
// 4. 遍历数据行(跳过第一行统计数据)
for (let i = 1; i < rows.length; i++) {
const cells = rows[i].querySelectorAll("td");
// 5. 固定位置第 6 列(索引 5)为 "回调时间(GMT+0:00)"
const timeCell = cells[5]?.querySelector(".cell");
if (!timeCell) continue;
const timeText = timeCell.textContent.trim();
if (!timeText) continue;
// 6. 解析日期字符串
const recordDate = new Date(timeText); // 假设 timeText 是 GMT+0 时间
if (
recordDate.getUTCFullYear() === todayGMT0Year &&
recordDate.getUTCMonth() === todayGMT0Month &&
recordDate.getUTCDate() === todayGMT0Date
) {
todayCount++;
}
}
console.log(
`当天提现记录数: ${todayCount},限制次数: ${config.maxWithdrawTimes}`
);
// 7. 判断是否超限
if (todayCount > config.maxWithdrawTimes) {
updateStatus(`用户 ${config.currentUserId} 当天提现次数超过限制`);
markOrderAsProcessed(config.currentOrderId, "提现次数超限");
config.processingOrderId = null;
returnToOrderPage();
return;
}
// 8. 次数满足,检查 CoinPay 提现记录
checkCoinPayWithdraw();
}
function continueProcessing() {
config.processingOrderId = null;
setTimeout(processOrderPage, 500);
}
// 检查CoinPay提现记录
function checkCoinPayWithdraw() {
console.log("正在检查CoinPay提现记录...");
// 找到第三方下拉选择框
const thirdPartySelect = document.querySelector(
'.el-select input[placeholder="全部"]'
);
if (!thirdPartySelect) {
console.error("找不到第三方下拉选择框");
setTimeout(() => {
checkCoinPayWithdraw();
}, 1000);
return;
}
// 点击下拉框
thirdPartySelect.click();
// 等待下拉菜单出现
setTimeout(() => {
// 查找下拉菜单容器(可能在body的末尾)
const dropdown = document.querySelectorAll(
".el-select-dropdown.el-popper"
);
if (!dropdown) {
console.error("找不到下拉菜单");
returnToOrderPage();
return;
}
const coinPayItems = dropdown[2]; // 取第二个
// 查找CoinPay选项
const items = coinPayItems.querySelectorAll(".el-select-dropdown__item");
let coinPayItem = null;
for (const item of items) {
if (item.textContent.trim().toLowerCase() === "coinpay") {
coinPayItem = item;
break;
}
}
if (!coinPayItem) {
console.error("找不到CoinPay选项");
// 没有CoinPay选项,继续代理检查
updateStatus(
`用户 ${config.currentUserId} 无CoinPay提现记录,检查代理条件`
);
setTimeout(() => {
window.location.href = "#/agent/agent-list";
}, 1000);
return;
}
// 选择CoinPay选项
coinPayItem.click();
// 点击查询按钮
setTimeout(() => {
adjustDateTimeRange7d();
const queryBtn = Array.from(
document.querySelectorAll(".filter-container button.el-button")
).find((btn) => {
const span = btn.querySelector("span");
return span && span.textContent.trim() === "查询";
});
if (queryBtn) {
queryBtn.click();
// 检查查询结果
setTimeout(() => {
// 检查是否有"暂无数据"提示
const emptyText = document.querySelector(".el-table__empty-text");
if (emptyText && emptyText.textContent.includes("暂无数据")) {
console.log("没有CoinPay提现记录");
// 没有CoinPay提现记录,继续代理检查
updateStatus(
`用户 ${config.currentUserId} 无CoinPay提现记录,检查代理条件`
);
setTimeout(() => {
window.location.href = "#/agent/agent-list";
}, 1000);
return;
}
// 检查表格行数
const coinPayRows = document.querySelectorAll(
".el-table__body .el-table__row"
);
// 减1是因为第一行是统计数据
const length = coinPayRows.length > 0 ? coinPayRows.length - 1 : 0;
console.log("CoinPay提现记录:", length);
if (length > 0) {
// 有CoinPay提现记录
updateStatus(`用户 ${config.currentUserId} 有CoinPay提现记录`);
markOrderAsProcessed(config.currentOrderId, "有CoinPay提现记录");
config.processingOrderId = null;
returnToOrderPage();
} else {
// 没有CoinPay提现记录,继续代理检查
updateStatus(
`用户 ${config.currentUserId} 无CoinPay提现记录,检查代理条件`
);
setTimeout(() => {
window.location.href = "#/agent/agent-list";
}, 1000);
}
}, 2000);
}
}, 500);
}, 500);
}
// 关闭弹窗并继续处理
function closeDialogAndContinue() {
closeDialog();
config.processingOrderId = null;
const rows = document.querySelectorAll(".el-table__body .el-table__row");
if (config.currentProcessingRow > 0) {
config.currentProcessingRow--;
setTimeout(processOrderPage, 500);
} else {
// 当前页处理完成
if (config.currentPage > 1) {
goToPrevPage();
waitForTableUpdate(processOrderPage); // 👈 加上这个
} else {
setTimeout(processOrderPage, 1000);
}
}
}
function waitForTableUpdate(callback, retry = 10) {
let lastRowCount = document.querySelectorAll('.el-table__body .el-table__row').length;
const check = () => {
const newRowCount = document.querySelectorAll('.el-table__body .el-table__row').length;
if (newRowCount !== lastRowCount && newRowCount > 0) {
setTimeout(callback, 200); // 再等一点点以确保页面稳定
} else if (retry > 0) {
retry--;
setTimeout(check, 300); // 继续检查
} else {
console.warn("表格未及时刷新,强制继续");
callback();
}
};
setTimeout(check, 300);
}
// 关闭弹窗
function closeDialog() {
const closeBtn = document.querySelector(
'.el-dialog__wrapper:not([style*="display: none"]) .el-dialog__headerbtn'
);
if (closeBtn) closeBtn.click();
}
// 处理代理页面
function processAgentPage() {
if (!config.isProcessing) return;
console.log("正在处理代理页面,用户ID:", config.currentUserId);
// 使用MutationObserver确保DOM完全加载
const observer = new MutationObserver((mutations, obs) => {
const searchContainer = document.querySelector(".filter-container");
if (!searchContainer) return;
// 找到用户ID输入框
const idInput = searchContainer.querySelector(
'input.el-input__inner[placeholder="请输入用户ID"]'
);
if (!idInput) return;
obs.disconnect(); // 停止观察
// 清空现有值
const setter = Object.getOwnPropertyDescriptor(
HTMLInputElement.prototype,
"value"
).set;
setter.call(idInput, "");
idInput.dispatchEvent(new Event("input", { bubbles: true }));
// 设置新值
setTimeout(() => {
setter.call(idInput, config.currentUserId);
idInput.dispatchEvent(new Event("input", { bubbles: true }));
idInput.dispatchEvent(new Event("change", { bubbles: true }));
// 查找查询按钮
const queryBtn = Array.from(
searchContainer.querySelectorAll("button.el-button")
).find((btn) => btn.textContent.includes("查询"));
if (queryBtn) {
console.log("找到查询按钮,正在点击...");
queryBtn.click();
setTimeout(checkAgentResult, 2000);
} else {
console.error("未找到查询按钮");
setTimeout(checkAgentResult, 1000);
}
}, 300);
});
observer.observe(document.body, {
childList: true,
subtree: true,
});
// 设置超时回退
setTimeout(() => {
if (observer) observer.disconnect();
}, 5000);
}
// 检查代理结果
function checkAgentResult() {
console.log("正在检查代理结果...");
// 获取所有代理信息表格的行
const rows = document.querySelectorAll(".el-table__body .el-table__row");
console.log("找到的行数:", rows.length);
// 如果没有任何代理信息,认为无结果,直接返回订单页面
if (rows.length === 0) {
updateStatus(`用户 ${config.currentUserId} 无代理信息,返回订单页面`);
config.processingOrderId = null; // 清空当前处理订单ID
returnToOrderPage(); // 跳转回订单页面
return;
}
// 取第一行数据进行判断,假设只关注第一条代理记录
const row = rows[0];
// 取该行所有单元格(td),通过索引定位需要的列
const cells = row.querySelectorAll("td");
// 获取上级代理(第2列)
let superiorAgent = "";
const agentCell = cells[1];
if (agentCell) {
const span =
agentCell.querySelector(".el-tooltip") ||
agentCell.querySelector("span");
if (span) {
superiorAgent = span.textContent.trim();
}
}
console.log("上级代理(提取后):", JSON.stringify(superiorAgent));
// --- 获取直推成员数量 ---
// 直推成员数量在第4列(td索引3),查询该单元格内的 span 元素文本,转为整数
let directMembers = 0;
const directMembersSpan = cells[3]?.querySelector(".cell > span");
if (directMembersSpan) {
directMembers = parseInt(directMembersSpan.textContent.trim()) || 0; // 转成数字,失败默认0
}
console.log("上级代理:", superiorAgent);
console.log("直推成员:", directMembers);
// 判断代理条件:
// 如果存在上级代理且直推成员 >= 1,条件不满足,标记订单并返回
if (superiorAgent || directMembers >= 1) {
config.processingOrderId = null; // 清空订单ID,结束当前流程
updateStatus(`用户 ${config.currentUserId} 代理条件不满足,返回订单页面`);
markOrderAsProcessed(config.currentOrderId, "不满足条件"); // 标记订单为已处理,备注原因
returnToOrderPage();
return;
}
// 代理条件满足,设置标识,准备执行后续操作
updateStatus(`用户 ${config.currentUserId} 代理条件满足,返回执行出款`);
config.needApprove = true; // 标记需要审批(或后续流程)
returnToOrderPage();
}
// 返回到订单页面
function returnToOrderPage() {
if (config.isReturning) return;
config.isReturning = true;
console.log("正在返回订单页面...");
// 跳转前清除搜索条件
clearAllSearchInputs();
window.location.href = "#/order/unread-withdraw";
let retryCount = 0;
const maxRetries = 5;
const checkPageLoaded = setInterval(() => {
if (isOrderPage()) {
clearInterval(checkPageLoaded);
config.isReturning = false;
// 确保订单表格已加载
const checkTableLoaded = setInterval(() => {
const rows = document.querySelectorAll(
".el-table__body .el-table__row"
);
if (rows.length > 0 || ++retryCount >= maxRetries) {
clearInterval(checkTableLoaded);
if (config.needApprove) {
console.log("准备执行出款操作...");
setTimeout(() => {
approveOrder();
config.needApprove = false;
}, 1500);
} else {
setTimeout(processOrderPage, 1000);
}
}
}, 500);
} else if (++retryCount >= maxRetries) {
clearInterval(checkPageLoaded);
config.isReturning = false;
setTimeout(processOrderPage, 3000);
}
}, 500);
}
// 批准订单(优化版)
function approveOrder() {
if (!config.isProcessing) return;
// 找到当前订单的行
const rows = document.querySelectorAll(".el-table__body .el-table__row");
for (let i = rows.length - 1; i >= 0; i--) {
const row = rows[i];
const orderId = getOrderIdFromRow(row);
if (orderId === config.currentOrderId) {
// 点击"待审核大额"按钮(优化选择器)
// --- 通过固定列索引获取“订单状态”单元格 ---
// HTML结构中“订单状态”在第11列,索引是10(从0开始)
const cells = row.querySelectorAll("td");
const statusCell = cells[10]; // 第11列单元格
if (statusCell) {
// 单元格内的span文本是状态文字,比如“待审核大额”
const statusSpan = statusCell.querySelector(".cell > span");
if (statusSpan && statusSpan.textContent.includes("待审核")) {
statusSpan.click();
// 等待弹窗出现的改进方案
const waitForDialog = (attempt = 0) => {
if (attempt > 5) {
updateStatus(`订单 ${orderId} 弹窗未出现,跳过处理`);
config.needApprove = false;
setTimeout(processOrderPage, 500);
return;
}
const dialog = document.querySelector(
'.el-dialog__wrapper:not([style*="display: none"])'
);
if (dialog) {
handleDialog(dialog, orderId);
} else {
setTimeout(() => waitForDialog(attempt + 1), 800);
}
};
const handleDialog = (dialog, orderId) => {
const findPasswordInput = () =>
dialog.querySelector(
'.myDialog input.el-input__inner:not([type="hidden"])'
) ||
dialog.querySelector(
'.el-dialog__body input.el-input__inner:not([type="hidden"])'
);
const fastSetValue = (input, value) => {
const nativeSetter = Object.getOwnPropertyDescriptor(
HTMLInputElement.prototype,
"value"
)?.set;
nativeSetter
? nativeSetter.call(input, value)
: (input.value = value);
input.dispatchEvent(new Event("input", { bubbles: true }));
};
const clickApproveAndHandle = () => {
const approveBtn = dialog.querySelector(".el-button--success");
if (!approveBtn) {
updateStatus(`订单 ${orderId}:未找到“同意出款”按钮`);
return;
}
approveBtn.click();
updateStatus(`订单 ${orderId} 正在处理中...`);
// 等确认弹窗出来再点“确定”
const waitConfirm = setInterval(() => {
const confirmDialog = document.querySelector(
'.el-message-box__wrapper:not([style*="display: none"])'
);
if (confirmDialog) {
clearInterval(waitConfirm);
const confirmBtn = confirmDialog.querySelector(
".el-button--primary"
);
if (confirmBtn) confirmBtn.click();
handleApprovalSuccess(orderId);
}
}, 200);
};
const input = findPasswordInput();
if (input) {
fastSetValue(input, config.password);
// 等待一次事件循环,确保绑定值更新
setTimeout(clickApproveAndHandle, 100);
} else {
const observer = new MutationObserver((_, obs) => {
const i = findPasswordInput();
if (i) {
obs.disconnect();
fastSetValue(i, config.password);
setTimeout(clickApproveAndHandle, 100);
}
});
observer.observe(dialog, { childList: true, subtree: true });
setTimeout(() => observer.disconnect(), 3000);
}
};
const handleApprovalSuccess = (orderId) => {
updateStatus(`订单 ${orderId} 已批准`);
config.processedOrders[config.currentOrderId] = true;
GM_setValue("processedOrders", config.processedOrders);
document.getElementById("processedCount").textContent =
Object.keys(config.processedOrders).length;
markOrderAsProcessed(orderId, "已批准");
config.payOutOrders[config.currentOrderId] = true;
GM_setValue("payOutOrders", config.payOutOrders);
document.getElementById("payOutOrders").textContent = Object.keys(
config.payOutOrders
).join(", ");
// === 新增:延迟检查出款弹窗是否仍然存在 ===
setTimeout(() => {
const payoutDialog = document.querySelector(
'.el-dialog__wrapper:not([style*="display: none"]) .el-dialog__title'
);
if (
payoutDialog &&
payoutDialog.textContent.includes("订单操作")
) {
updateStatus(`订单 ${orderId} 出款可能失败,关闭弹窗继续`);
const closeBtn = document.querySelector(
'.el-dialog__wrapper:not([style*="display: none"]) .el-dialog__headerbtn'
);
if (closeBtn) closeBtn.click();
}
}, 500); // 0.5秒后检查
// 继续处理下一个订单
setTimeout(() => {
config.needApprove = false;
config.processingOrderId = null;
setTimeout(processOrderPage, 1000);
}, 1000);
};
waitForDialog();
return;
}
}
}
}
// 没找到订单,继续处理
config.needApprove = false;
setTimeout(processOrderPage, 500);
}
// 新增标记订单函数
function markOrderAsProcessed(orderId, reason = "") {
if (!orderId) return;
config.processedOrders[orderId] = {
time: new Date().toISOString(),
reason: reason || "已处理",
};
GM_setValue("processedOrders", config.processedOrders);
document.getElementById("processedCount").textContent = Object.keys(
config.processedOrders
).length;
console.log(
`订单 ${orderId} 已标记为已处理`,
reason ? `原因: ${reason}` : ""
);
}
// 从行中获取订单ID(优化版)
function getOrderIdFromRow(row) {
// 1. 先找到包含"订单号"的表头单元格
const headerCells = document.querySelectorAll(".el-table__header .cell");
const orderHeader = Array.from(headerCells).find(
(cell) => cell.textContent.trim() === "订单号"
);
if (orderHeader) {
// 2. 获取列索引
const colIndex = orderHeader.closest("th").getAttribute("aria-colindex");
if (colIndex) {
// 3. 使用列索引找到对应数据单元格
const orderIdEl = row.querySelector(
`td:nth-child(${colIndex}) .cell > span`
);
if (orderIdEl) {
return orderIdEl.textContent.trim();
}
}
}
// 备用方案:通过内容特征匹配
const cells = Array.from(row.querySelectorAll(".cell > span"));
const idCell = cells.find((cell) => {
const text = cell.textContent.trim();
return /^tx_\d+_\d{8}\w+$/.test(text); // 匹配订单号格式
});
return idCell ? idCell.textContent.trim() : "";
}
// 初始化
function init() {
// 初始化控制面板
addControlPanel();
// 检查是否已完成一轮处理
config.completedOneRound = GM_getValue("completedOneRound", false);
if (config.completedOneRound) {
updateStatus("检测到已完成一轮处理,开始新一轮处理");
GM_setValue("completedOneRound", false);
config.processedOrders = {}; // 清空已处理订单记录
GM_setValue("processedOrders", {});
document.getElementById("processedCount").textContent = "0";
}
updateStatus("准备就绪");
// 监听hash变化
window.addEventListener("hashchange", () => {
if (!config.isProcessing) return;
if (isOrderPage()) {
processOrderPage();
} else if (isAgentPage()) {
processAgentPage();
} else if (window.location.hash.includes("#/order/order-withdraw")) {
processWithdrawOrderPage();
} else if (window.location.hash.includes("#/order/order-topup")) {
processTopupOrderPage();
}
});
// 如果当前已经在订单页面且正在处理中,直接开始处理
if (config.isProcessing && isOrderPage()) {
updateStatus("恢复处理中...");
processOrderPage();
}
}
// 页面加载完成后执行
if (document.readyState === "complete") {
init();
} else {
window.addEventListener("load", init);
}
})();