您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
根据多重条件自动审核大额订单
当前为
// ==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); } })();