]*>([^<]{4,200})<\/li>/i,
/class="error[^"]*"[^>]*>([^<]+)/i,
/errorMessage[^>]*>([^<]+)/i,
];
for (let i = 0; i < pats.length; i++) {
const m = text.match(pats[i]);
if (m && m[1] && m[1].trim()) return m[1].replace(/\s+/g, ' ').trim();
}
if (text.includes('セッションがタイムアウト') || text.includes('セキュリティのため')) {
return '会话超时,请刷新页面重新登录后再提交';
}
return '';
}
function looksExecuteSuccess(resp) {
const t = (resp && resp.text) || '';
const u = (resp && resp.url) || '';
if (t.includes('会員情報を更新しました')) return true;
if (t.includes('form-message') && t.includes('更新しました')) return true;
if (u.includes('member_regist_confirm') && t.includes('更新')) return true;
return false;
}
function parseToken(html) {
const m = (html || '').match(/name="token"\s+value="([0-9a-f]+)"/i);
return m ? m[1] : '';
}
function parseMemberData(html) {
const m = (html || '').match(/var\s+member_data\s*=\s*(\{[\s\S]*?\})\s*;/);
if (!m) return {};
try {
return JSON.parse(m[1]);
} catch (e) {
return {};
}
}
function parseProfile(html) {
const md = parseMemberData(html);
let tel = parseInput(html, 'TEL');
if (!tel) {
const tm = html.match(/(?×
Bandai Parks 会员资料(v0.10.1)
「读取姓名」直接解析当前页面 DOM(零请求);「提交」时才联网走登录态拿 token。
⚠ 读取不联网一定成功;提交会真实修改服务器资料(姓名+生日)。
就绪:点「读取姓名」从当前页面 DOM 提取。
`;
document.body.appendChild(icon);
document.body.appendChild(panel);
const logEl = panel.querySelector('#cpxLog');
const setLog = (msg) => { logEl.textContent = msg; };
const open = () => panel.classList.add('open');
const close = () => panel.classList.remove('open');
icon.addEventListener('click', () => {
if (panel.classList.contains('open')) close();
else open();
});
panel.querySelector('#cpxClose').addEventListener('click', close);
// 读取:直接读当前页面 DOM(零请求)
panel.querySelector('#cpxLoad').addEventListener('click', () => {
reportLog('用户点击「读取姓名」');
const n = readNameFromDom();
if (!n) {
setLog('❌ 当前页面没有姓名信息。\n请到以下页面再点:\n• 编辑页 member_regist.html?request=edit\n• 会员页 member_mypage.html');
return;
}
panel.querySelector('#cpxL').value = n.last_name;
panel.querySelector('#cpxF').value = n.first_name;
setLog('✅ 已从页面 DOM 读取(来源:' + n.source + ')\n姓:' + n.last_name + '\n名:' + n.first_name);
});
panel.querySelector('#cpxClear').addEventListener('click', () => {
panel.querySelector('#cpxL').value = '';
panel.querySelector('#cpxF').value = '';
panel.querySelector('#cpxB').value = '';
setLog('已清空。');
});
// 提交:登录态 confirm → execute(拿 token)
panel.querySelector('#cpxSubmit').addEventListener('click', async () => {
const ln = panel.querySelector('#cpxL').value.trim();
const fn = panel.querySelector('#cpxF').value.trim();
const bRaw = panel.querySelector('#cpxB').value.trim();
const pwd = panel.querySelector('#cpxP').value;
if (!ln || !fn) { setLog('请先读取或填写姓和名'); return; }
if (!pwd) { setLog('请填写登录密码'); return; }
setLog('提交中…(confirm → execute,最多等 60 秒)');
reportLog('用户点击「提交」姓=' + ln + ' 名=' + fn);
try {
const profile = await loadProfileForSubmit();
const res = await submitNameBirthday(profile, ln, fn, bRaw, pwd);
setLog('✅ 已提交到服务器并永久生效\n新氏名:' + res.last_name + ' ' + res.first_name + '\n生日:' + res.birthday);
} catch (e) {
setLog('❌ ' + e.message);
}
});
}
/* ---------- 启动 ---------- */
function boot() {
reportLog('BOOT UI v0.10.1');
if (document.body) {
buildUI();
reportLog('UI 已注入');
return;
}
const t = setInterval(() => {
if (document.body) {
clearInterval(t);
buildUI();
reportLog('UI 已注入');
}
}, 200);
}
boot();
})();