AI直接搓个脚本就行了 // ==UserScript== // @name 中国银行预选卡号 / 制卡进度 // @namespace https://open.boc.cn/ // @version 1.1.0 // @description 读取中国银行申请查询页面中的预选卡号和制卡进度 // @match https://open.boc.cn/bankcard/cardReserve/* // @run-at document-idle // @grant none // ==/UserScript== (function () { 'use strict'; const STATUS_MAP = { '00': '待制卡', '01': '制卡中', '02': '流程异常', '03': '制卡完毕,已寄出到网点', '04': '待领卡', '05': '流程异常', '06': '已领卡', '07': '流程异常' }; let lastCardNo = null; let lastStatus = null; /* * 只读取原教程指定的数据。 * 不修改 Vue 对象,也不修改中行网页原有 DOM。 */ function readRecordInfo() { try { const el = document.querySelector('.progress-result-wrap'); if (!el) { return null; } const vue = el.__vue__; if (!vue) { return null; } /* * 原教程: * el.__vue__.$parent.recordInfo */ if ( vue.$parent && vue.$parent.recordInfo ) { return vue.$parent.recordInfo; } /* * 防止 Vue 层级有小变化。 * 最多向上找 8 层。 */ let current = vue; for (let i = 0; i < 8; i++) { if (!current) { break; } if (current.recordInfo) { return current.recordInfo; } current = current.$parent; } } catch (error) { console.warn( '[BOC] 读取数据失败:', error ); } return null; } function escapeHtml(value) { return String(value ?? '') .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } /* * 创建完全独立的显示窗口。 * * 不使用原网页 class。 * 不修改 progress-result-wrap。 */ function showInfo(cardNo, statusCode) { const statusText = STATUS_MAP[statusCode] || `未知状态 (${statusCode || '无'})`; let panel = document.getElementById( '__boc_card_reader_panel__' ); if (!panel) { panel = document.createElement('div'); panel.id = '__boc_card_reader_panel__'; panel.style.cssText = [ 'position:fixed', 'right:20px', 'bottom:20px', 'width:320px', 'max-width:calc(100vw - 40px)', 'padding:18px', 'box-sizing:border-box', 'background:#fff', 'color:#222', 'border:1px solid #ddd', 'border-radius:12px', 'box-shadow:0 6px 24px rgba(0,0,0,.18)', 'font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Microsoft YaHei",sans-serif', 'z-index:2147483647' ].join(';'); document.body.appendChild(panel); } panel.innerHTML = ` <div style=" display:flex; justify-content:space-between; align-items:center; margin-bottom:16px; " > <strong style="font-size:17px;"> 💳 制卡信息 </strong> <button id="__boc_close__" style=" border:0; background:transparent; font-size:22px; cursor:pointer; color:#888; " > × </button> </div> <div style=" color:#888; font-size:12px; margin-bottom:5px; " > 预选卡号 </div> <div style=" font-size:19px; font-weight:600; margin-bottom:16px; word-break:break-all; user-select:text; " > ${escapeHtml(cardNo)} </div> <div style=" color:#888; font-size:12px; margin-bottom:5px; " > 制卡进度 </div> <div style=" font-size:17px; font-weight:600; margin-bottom:5px; " > ${escapeHtml(statusText)} </div> <div style=" color:#999; font-size:12px; margin-bottom:16px; " > 状态码:${escapeHtml(statusCode)} </div> <button id="__boc_copy__" style=" width:100%; border:0; border-radius:8px; padding:10px; background:#b30019; color:#fff; cursor:pointer; " > 复制卡号 </button> `; const closeButton = panel.querySelector( '#__boc_close__' ); closeButton.onclick = function () { panel.remove(); }; const copyButton = panel.querySelector( '#__boc_copy__' ); copyButton.onclick = async function () { try { await navigator.clipboard.writeText( cardNo ); copyButton.textContent = '✓ 已复制'; setTimeout(() => { copyButton.textContent = '复制卡号'; }, 1200); } catch (error) { prompt( '请手动复制卡号:', cardNo ); } }; } function check() { const info = readRecordInfo(); /* * 页面还在登录、验证码、 * 填表等阶段时什么都不做。 */ if (!info) { return; } const cardNo = String( info.cardNo ?? '' ).trim(); const statusCode = String( info.mkcrdProgreSts ?? '' ).trim(); /* * 没有读取到任何有效内容, * 继续等待。 */ if (!cardNo && !statusCode) { return; } /* * 内容没变化时不碰 DOM。 */ if ( cardNo === lastCardNo && statusCode === lastStatus ) { return; } lastCardNo = cardNo; lastStatus = statusCode; console.log( '[BOC] 预选卡号:', cardNo ); console.log( '[BOC] 制卡状态:', statusCode, STATUS_MAP[statusCode] || '未知' ); console.log( '[BOC] recordInfo:', info ); showInfo( cardNo || '未获取到', statusCode ); } /* * 重点: * * 不使用 MutationObserver。 * 不监听页面 DOM 更新。 * * 只每秒进行一次只读检查。 */ setInterval( check, 1000 ); /* * 页面加载后先检查一次。 */ setTimeout( check, 1500 ); })();
卡号不是自定义的吗。早就知道卡号了呀
@天道酬善 #11 在选完后六位的时候就出卡号了 选完才给提交的
AI直接搓个脚本就行了