本帖最后由 zxinyun 于 2026-4-21 12:37 编辑
[HTML] 纯文本查看 复制代码 ❌ 错误:Unexpected token '<', "<!doctype "... is not valid JSON
改良一下:
[JavaScript] 纯文本查看 复制代码 // ==UserScript==
// [url=home.php?mod=space&uid=170990]@name[/url] 粉笔行测助手 v7.5
// [url=home.php?mod=space&uid=467642]@namespace[/url] https://fenbi.com/
// [url=home.php?mod=space&uid=1248337]@version[/url] 7.5
// @description 强制物理顺序 1:1 对齐,解决材料题导致的答案移位问题
// [url=home.php?mod=space&uid=195849]@match[/url] *://*.fenbi.com/*
// [url=home.php?mod=space&uid=609072]@grant[/url] GM_addStyle
// @run-at document-end
// ==/UserScript==
(async function () {
console.log("✅ 粉笔助手 v7.5 启动 - 纯净对齐模式");
GM_addStyle(`
#fbHelper {
position: fixed; top: 120px; left: 10px; width: 180px;
background: #fff; border: 2px solid #165DFF; z-index: 2147483647;
padding: 10px; border-radius: 10px; box-shadow: 0 8px 20px rgba(0,0,0,0.15);
}
.fb-btn {
width: 100%; padding: 8px; background: #165DFF; color: #fff;
border: none; border-radius: 4px; cursor: pointer; font-size: 12px; font-weight: bold;
}
#fbAnsList {
max-height: 250px; overflow-y: auto; margin-top: 10px;
font-size: 13px; background: #fdfdfd; padding: 5px; border-radius: 5px; border: 1px solid #eee;
}
.ans-item { display: inline-block; width: 45%; margin: 2px; color: #333; border-bottom: 1px solid #f0f0f0; }
.ans-item b { color: #165DFF; }
.fb-stat { display: block; text-align: center; font-size: 11px; color: #165DFF; margin-top: 5px; }
`);
function createUI() {
if (document.getElementById('fbHelper')) return;
const div = document.createElement('div');
div.id = 'fbHelper';
div.innerHTML = `
<div style="font-size:12px;font-weight:bold;color:#165DFF;margin-bottom:6px;text-align:center;">粉笔助手 v7.5</div>
<button class="fb-btn" id="fbRun">同步并 1:1 填充</button>
<span id="fbStat" class="fb-stat">就绪</span>
<div id="fbAnsList">等待同步...</div>
`;
document.body.appendChild(div);
document.getElementById('fbRun').onclick = startWork;
}
// 强制 1:1 顺序填充
async function forceSequenceFill(ansChoices) {
// 1. 寻找所有包含选项列表的 <ul> 容器,这才是真正的题目交互区
const questionLists = Array.from(document.querySelectorAll('ul.choice-radios, .choice-radios'));
let filledCount = 0;
questionLists.forEach((ul, index) => {
// index 0 对应第一个 <ul> (即第1题),index 1 对应第2题...
const correctIdx = ansChoices[index];
if (correctIdx !== undefined && correctIdx !== null) {
// 寻找该 <ul> 下的第几个 <li>
const options = ul.querySelectorAll('li.choice-radio, .choice-radio');
if (options.length > correctIdx) {
const targetLi = options[correctIdx];
// 模拟点击 label 或内部的 input-radio
const clicker = targetLi.querySelector('.input-radio') || targetLi.querySelector('label') || targetLi;
clicker.click();
// 触发 Angular 状态变更
const input = targetLi.querySelector('input');
if (input) {
input.dispatchEvent(new Event('change', { bubbles: true }));
}
filledCount++;
}
}
});
return filledCount;
}
async function startWork() {
const list = document.getElementById('fbAnsList');
const stat = document.getElementById('fbStat');
list.innerText = "数据同步中...";
try {
const ress = performance.getEntriesByType('resource');
const apiEntry = ress.find(r => r.name.includes('tiku.fenbi.com/combine/static/exercise') || r.name.includes('tiku.fenbi.com/api/xingce/exercises'));
if (!apiEntry) {
list.innerText = "❌ 未发现数据,请刷新。";
return;
}
const res = await fetch(apiEntry.name, { credentials: 'include' });
const data = await res.json();
const ids = (data.questions || []).map(q => q.id).filter(id => id);
const idsStr = ids.join(',');
const ansRes = await fetch('https://tiku.fenbi.com/api/xingce/questions?ids=' + idsStr, { credentials: 'include' });
const ansData = await ansRes.json();
let ansChoices = [];
let html = "";
ids.forEach((id) => {
const item = ansData.find(a => String(a.id) === String(id));
const choice = item ? item.correctAnswer?.choice : null;
ansChoices.push(choice);
const char = (choice !== null && choice !== undefined) ? ["A", "B", "C", "D"][choice] : "?";
html += `<div class="ans-item">${ansChoices.length}: <b>${char}</b></div>`;
});
list.innerHTML = html;
stat.innerText = "正在 1:1 填充...";
// 执行 3 轮滚动扫描,确保懒加载题目被触发
for (let i = 0; i < 3; i++) {
const num = await forceSequenceFill(ansChoices);
if (num >= ids.length) break;
window.scrollBy(0, 800);
await new Promise(r => setTimeout(r, 600));
}
window.scrollTo(0, 0);
stat.innerText = "✨ 填充完成";
} catch (e) {
list.innerText = "❌ 错误:" + e.message;
}
}
setTimeout(createUI, 1500);
})();
|