xOf(value) === index; }) .sort(function (a, b) { return a - b; }); }); return base; } catch (error) { return createState(); } } function saveState(state) { window.localStorage.setItem(STORAGE_KEY, JSON.stringify(state)); } function buildMetrics(h, t, o) { var pairDiffs = [Math.abs(h - t), Math.abs(h - o), Math.abs(t - o)]; var pairSumTails = [(h + t) % 10, (h + o) % 10, (t + o) % 10]; return { sum: h + t + o, span: Math.max(h, t, o) - Math.min(h, t, o), pairDiffs: pairDiffs, pairSumTails: pairSumTails }; } function matches(state, h, t, o) { var metrics = buildMetrics(h, t, o); if (state.sum.length && state.sum.indexOf(metrics.sum) === -1) return false; if (state.pairSumTail.length && !metrics.pairSumTails.some(function (value) { return state.pairSumTail.indexOf(value) !== -1; })) return false; if (state.pairDiff.length && !metrics.pairDiffs.some(function (value) { return state.pairDiff.indexOf(value) !== -1; })) return false; if (state.span.length && state.span.indexOf(metrics.span) === -1) return false; if (state.dan.length && state.dan.indexOf(h) === -1 && state.dan.indexOf(t) === -1 && state.dan.indexOf(o) === -1) return false; if (state.hundreds.length && state.hundreds.indexOf(h) === -1) return false; if (state.tens.length && state.tens.indexOf(t) === -1) return false; if (state.ones.length && state.ones.indexOf(o) === -1) return false; return true; } function buildResultText(results) { var lines = []; results.forEach(function (item, index) { var lineIndex = Math.floor(index / 10); if (!lines[lineIndex]) lines[lineIndex] = []; lines[lineIndex].push(item); }); return lines.map(function (line) { return line.join(' '); }).join('\n'); } function buildTagFromNumber(numberText) { var digits = normalizeThreeDigits(numberText); if (digits.length !== 3) return ''; var sum = digits.reduce(function (total, digit) { return total + Number(digit); }, 0); return digits.slice().sort().join('') + ':' + sum; } function extractDrawItems(payload) { if (Array.isArray(payload && payload.draws)) { return payload.draws; } var items = []; ['fc3d', 'pl3'].forEach(function (key) { if (payload && payload[key]) { items.push(Object.assign({ key: key }, payload[key])); } }); return items; } function readLineGroupData() { try { return JSON.parse(window.localStorage.getItem('lineGroupData_v2') || '{}'); } catch (error) { return {}; } } function buildResultTagMap(results) { return results.map(function (result) { return { value: result, tag: buildTagFromNumber(result), }; }); } function buildRecentReferenceContext(payload) { var lineGroupData = readLineGroupData(); var draws = extractDrawItems(payload); var recentTags = []; draws .filter(function (item) { return item && (item.key === 'fc3d' || item.key === 'pl3'); }) .forEach(function (item) { var recentDraws = Array.isArray(item.recent_draws) && item.recent_draws.length ? item.recent_draws : [{ front_numbers: item.front_numbers }]; recentDraws.slice(0, 2).forEach(function (draw, periodIndex) { var display = buildDisplay(draw.front_numbers); var tag = buildTagFromNumber(display); if (!tag) return; recentTags.push({ issue: draw.issue || '', source: item.key, periodIndex: periodIndex, display: display, tag: tag, lines: Array.isArray(lineGroupData[tag]) ? lineGroupData[tag] : [], }); }); }); var recentNodeIds = new Set(); recentTags.forEach(function (item) { item.lines.forEach(function (line) { if (line && line.start && line.start.id) recentNodeIds.add(line.start.id); if (line && line.end && line.end.id) recentNodeIds.add(line.end.id); }); }); return { recentTags: recentTags, recentNodeIds: recentNodeIds, lineGroupData: lineGroupData, }; } function analyzeResultConnectivity(results, payload) { var context = buildRecentReferenceContext(payload); return buildResultTagMap(results).map(function (item) { var lines = Array.isArray(context.lineGroupData[item.tag]) ? context.lineGroupData[item.tag] : []; var matchedRefs = []; context.recentTags.forEach(function (reference) { if (!reference.lines.length || !lines.length) return; var hit = lines.some(function (line) { return (line && line.start && context.recentNodeIds.has(line.start.id)) || (line && line.end && context.recentNodeIds.has(line.end.id)) || reference.lines.some(function (referenceLine) { if (!line || !referenceLine || !line.start || !line.end || !referenceLine.start || !referenceLine.end) return false; return line.start.id === referenceLine.start.id || line.start.id === referenceLine.end.id || line.end.id === referenceLine.start.id || line.end.id === referenceLine.end.id; }); }); if (hit) matchedRefs.push(reference); }); return { value: item.value, tag: item.tag, canConnect: matchedRefs.length > 0, matchedRefs: matchedRefs, lines: lines, }; }); } function buildLinesForResults(resultStates) { var lineGroupData = readLineGroupData(); var unique = new Map(); resultStates.forEach(function (result) { var tag = result.tag || buildTagFromNumber(result.value); var groupLines = Array.isArray(lineGroupData[tag]) ? lineGroupData[tag] : []; groupLines.forEach(function (line) { if (!line || !line.start || !line.end || !line.start.id || !line.end.id) return; var key = line.start.id + '->' + line.end.id; if (unique.has(key)) return; unique.set(key, { start: { id: line.start.id }, end: { id: line.end.id }, color: result.canConnect ? '#16a34a' : '#9ca3af', lineWeight: result.canConnect ? 8 : 5 }); }); }); return Array.from(unique.values()); } function renderLinesForResults(resultStates) { var nextLines = buildLinesForResults(resultStates); window.localStorage.setItem('linesData_v2', JSON.stringify(nextLines)); if (typeof window.clearCanvas === 'function') { window.clearCanvas(); } window.dispatchEvent(new Event('resize')); } function ensureStyles() { if (document.getElementById('mac-inline-filter-style')) return; var style = document.createElement('style'); style.id = 'mac-inline-filter-style'; style.textContent = [ '.mac-inline-filter{display:block;width:100%;margin-top:0;background:#fffdf8;border:1px solid #d4cabd;border-radius:8px;padding:10px 12px;box-sizing:border-box;position:relative;z-index:20;clear:both;flex:0 0 auto;}', '.workspace_panel,.workspace_panel .board_shell,.workspace_panel .grid_panel,.workspace_panel .connection_panel,.workspace_panel .container,.workspace_panel .grid,.workspace_panel .cell,.workspace_panel .cell *,.workspace_panel .connection_panel *{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none;}', '#touchCanvas,#lineCanvas{position:absolute !important;top:0 !important;left:0 !important;right:auto !important;bottom:auto !important;}', '#touchCanvas{pointer-events:none !important;cursor:crosshair;z-index:2 !important;background:transparent !important;}', '#lineCanvas{pointer-events:none !important;z-index:0 !important;background:transparent !important;}', '.workspace_panel > *:not(#touchCanvas):not(#lineCanvas){position:relative;z-index:12;}', '.connection_panel,.connection_panel .draggable{position:relative;}', '.connection_panel .draggable{z-index:5;}', '.mac-inline-filter-title-row{display:flex;align-items:center;justify-content:flex-start;gap:12px;margin-bottom:10px;flex-wrap:wrap;}', '.mac-inline-filter-title{font-size:15px;font-weight:700;color:#4c4338;}', '.mac-inline-filter-latest{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:12px;color:#6b6258;}', '.mac-inline-filter-latest-item{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;border:1px solid #dfd4c7;border-radius:999px;background:#fff;}', '.mac-inline-filter-latest-label{font-weight:700;color:#4c4338;}', '.mac-inline-filter-latest-value{font-weight:700;font-family:"SF Mono","SFMono-Regular","Menlo","Monaco","Consolas",monospace;letter-spacing:.04em;}', '.mac-inline-filter-grid{display:grid;grid-template-columns:repeat(2,max-content);justify-content:start;align-items:start;gap:4px 20px;width:max-content;max-width:100%;}', '.mac-inline-filter-field{min-width:0;display:flex;align-items:center;gap:8px;width:max-content;}', '.mac-inline-filter-label{display:inline-flex;align-items:center;flex:0 0 auto;font-size:13px;color:#5d5349;font-weight:600;line-height:34px;white-space:nowrap;}', '.mac-inline-filter-label.is-dan{color:#d63b33;}', '.mac-inline-filter-trigger{width:62px;min-width:62px;max-width:62px;height:34px;border:1px solid #d7cbbb;border-radius:6px;padding:0 22px 0 8px;background:#fff;color:#2f2a24;font-size:13px;box-sizing:border-box;text-align:left;cursor:pointer;display:inline-flex;align-items:center;justify-content:flex-start;position:relative;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}', '.mac-inline-filter-trigger::after{content:"▼";font-size:10px;color:#8b7e70;position:absolute;right:10px;top:50%;transform:translateY(-50%);}', '.mac-inline-filter-trigger.is-empty{color:transparent;}', '.mac-inline-filter-popup{position:absolute;left:0;top:64px;min-width:220px;background:#fffdf8;border:1px solid #d7cbbb;border-radius:8px;padding:8px;box-shadow:0 10px 24px rgba(0,0,0,.12);z-index:50;display:none;}', '.mac-inline-filter-popup.open{display:block;}', '.mac-inline-filter-options{display:flex;flex-wrap:wrap;gap:6px;max-height:160px;overflow:auto;}', '.mac-inline-filter-chip{min-width:32px;height:28px;padding:0 8px;border:1px solid #d6cab9;background:#f7f2e9;color:#5c5145;border-radius:14px;font-size:12px;line-height:26px;cursor:pointer;box-sizing:border-box;text-align:center;user-select:none;}', '.mac-inline-filter-chip.active{background:#d63b33;border-color:#d63b33;color:#fff;}', '.mac-inline-filter-field{position:relative;}', '.mac-inline-filter-actions{display:flex;align-items:center;gap:8px;margin-top:8px;flex-wrap:wrap;}', '.mac-inline-filter-submit,.mac-inline-filter-reset,.mac-inline-filter-copy{border:none;border-radius:6px;height:34px;padding:0 14px;font-size:13px;cursor:pointer;}', '.mac-inline-filter-submit{background:#d63b33;color:#fff;}', '.mac-inline-filter-reset{background:#eee4d5;color:#5d5349;}', '.mac-inline-filter-copy{background:#d8c8b2;color:#4c4338;}', '.mac-inline-filter-summary{font-size:12px;color:#6b6258;}', '.mac-inline-filter-result{margin-top:8px;padding-top:0;border-top:none;}', '.mac-inline-filter-result-header{display:flex;justify-content:space-between;align-items:center;gap:8px;margin-bottom:8px;}', '.mac-inline-filter-result-title{font-size:13px;font-weight:700;color:#4c4338;}', '.mac-inline-filter-result-count{font-size:12px;color:#6b6258;}', '.mac-inline-filter-result-text{width:100%;min-height:120px;resize:none;overflow:hidden;border:1px solid #d7cbbb;border-radius:6px;padding:10px;box-sizing:border-box;font-size:13px;line-height:1.6;color:#2f2a24;background:#fff;-webkit-user-select:text;user-select:text;}', '.mac-inline-filter-result-list{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px;}', '.mac-inline-filter-result-chip{display:inline-flex;align-items:center;height:28px;padding:0 10px;border-radius:14px;font-size:12px;font-weight:700;border:1px solid transparent;}', '.mac-inline-filter-result-chip.is-connect{background:rgba(22,163,74,.12);border-color:rgba(22,163,74,.35);color:#15803d;}', '.mac-inline-filter-result-chip.is-disconnect{background:rgba(156,163,175,.14);border-color:rgba(107,114,128,.28);color:#4b5563;}', '.mac-inline-filter-result-legend{display:flex;gap:10px;flex-wrap:wrap;font-size:12px;color:#6b6258;margin-top:8px;}', '.grid_panel{position:relative;z-index:20;}', '@media (max-width:1200px){.mac-inline-filter-grid{grid-template-columns:repeat(2,max-content);gap:4px 14px;}}', '@media (max-width:760px){.mac-inline-filter-grid{grid-template-columns:1fr;width:100%;}}' ].join(''); document.head.appendChild(style); } function createPanel() { var panel = document.createElement('div'); panel.className = 'mac-inline-filter'; panel.innerHTML = [ '
', '
', '3D--', '排三--', '
', '
条件筛选
', '
', '
', '
', '', '', '', '未选择的项不参与过滤', '
', '
', '
', '输出结果', '共 0 个', '
', '', '
绿色: 可连上近两期灰色: 当前连不上
', '
', '
' ].join(''); return panel; } function renderField(grid, state, field) { var fieldEl = document.createElement('div'); fieldEl.className = 'mac-inline-filter-field'; var label = document.createElement('span'); label.className = 'mac-inline-filter-label'; if (field.key === 'dan') { label.classList.add('is-dan'); } label.textContent = field.label; var trigger = document.createElement('button'); trigger.type = 'button'; trigger.className = 'mac-inline-filter-trigger'; var popup = document.createElement('div'); popup.className = 'mac-inline-filter-popup'; var options = document.createElement('div'); options.className = 'mac-inline-filter-options'; function updateTriggerText() { var selected = state[field.key]; if (!selected.length) { trigger.textContent = ' '; trigger.classList.add('is-empty'); return; } trigger.classList.remove('is-empty'); trigger.textContent = selected.join(', '); } field.options.forEach(function (option) { var chip = document.createElement('button'); chip.type = 'button'; chip.className = 'mac-inline-filter-chip'; if (state[field.key].indexOf(option) !== -1) chip.classList.add('active'); chip.textContent = String(option); chip.addEventListener('click', function () { var values = state[field.key]; var index = values.indexOf(option); if (index === -1) { values.push(option); values.sort(function (a, b) { return a - b; }); chip.classList.add('active'); } else { values.splice(index, 1); chip.classList.remove('active'); } updateTriggerText(); saveState(state); }); options.appendChild(chip); }); trigger.addEventListener('click', function (event) { event.stopPropagation(); document.querySelectorAll('.mac-inline-filter-popup.open').forEach(function (item) { if (item !== popup) item.classList.remove('open'); }); popup.classList.toggle('open'); }); popup.appendChild(options); updateTriggerText(); fieldEl.appendChild(label); fieldEl.appendChild(trigger); fieldEl.appendChild(popup); grid.appendChild(fieldEl); } function resolveMountTarget() { var workspacePanel = document.querySelector('.workspace_panel'); var boardShell = document.querySelector('.board_shell'); if (workspacePanel) { return { parent: workspacePanel, anchor: boardShell && boardShell.parentNode === workspacePanel ? boardShell : null, }; } if (boardShell) { return { parent: boardShell.parentNode || boardShell, anchor: boardShell, }; } var appRoot = document.querySelector('#app > div') || document.querySelector('#app'); return appRoot ? { parent: appRoot, anchor: null } : null; } function suppressWorkspaceSelection() { var workspace = document.querySelector('.workspace_panel'); if (!workspace || workspace.dataset.selectionGuardBound === '1') return; var allowSelector = '.mac-inline-filter, .mac-inline-filter *, textarea, input, button, select, option'; var handler = function (event) { if (event.target && event.target.closest && event.target.closest(allowSelector)) return; event.preventDefault(); }; workspace.addEventListener('selectstart', handler); workspace.addEventListener('dragstart', handler); workspace.dataset.selectionGuardBound = '1'; } function mountPanel() { ensureStyles(); suppressWorkspaceSelection(); var mountTarget = resolveMountTarget(); if (!mountTarget || !mountTarget.parent) return false; if (document.querySelector('.mac-inline-filter')) return true; var state = loadState(); var panel = createPanel(); var grid = panel.querySelector('.mac-inline-filter-grid'); var submitButton = panel.querySelector('.mac-inline-filter-submit'); var resetButton = panel.querySelector('.mac-inline-filter-reset'); var copyButton = panel.querySelector('.mac-inline-filter-copy'); var resultCount = panel.querySelector('.mac-inline-filter-result-count'); var resultText = panel.querySelector('.mac-inline-filter-result-text'); var resultList = panel.querySelector('.mac-inline-filter-result-list'); var latest3dEl = panel.querySelector('[data-latest-key="fc3d"]'); var latestPl3El = panel.querySelector('[data-latest-key="pl3"]'); async function syncLatestSummary() { try { var payload = await ensureLatestDrawPayload(); var draws = extractDrawItems(payload); draws.forEach(function (item) { if (!item || !item.key) return; var latest = Array.isArray(item.recent_draws) && item.recent_draws.length ? item.recent_draws[0] : item; var display = buildDisplay(latest && latest.front_numbers); var issue = (latest && latest.issue) || item.issue ? (' ' + ((latest && latest.issue) || item.issue || '')) : ''; if (item.key === 'fc3d' && latest3dEl) latest3dEl.textContent = display ? (display + issue) : '--'; if (item.key === 'pl3' && latestPl3El) latestPl3El.textContent = display ? (display + issue) : '--'; }); } catch (error) { if (latest3dEl) latest3dEl.textContent = '--'; if (latestPl3El) latestPl3El.textContent = '--'; } } function renderResultStates(resultStates) { resultList.innerHTML = ''; resultStates.forEach(function (item) { var chip = document.createElement('span'); chip.className = 'mac-inline-filter-result-chip ' + (item.canConnect ? 'is-connect' : 'is-disconnect'); chip.textContent = item.value; var refs = item.matchedRefs.map(function (ref) { return ref.display + (ref.issue ? ' ' + ref.issue : ''); }); chip.title = item.canConnect ? ('可连: ' + refs.join(' | ')) : '当前与近两期连不上'; resultList.appendChild(chip); }); } function syncResultHeight() { resultText.style.height = 'auto'; var nextHeight = Math.max(120, resultText.scrollHeight); resultText.style.height = nextHeight + 'px'; window.requestAnimationFrame(function () { resultText.style.height = 'auto'; resultText.style.height = Math.max(120, resultText.scrollHeight) + 'px'; }); } fields.forEach(function (field) { renderField(grid, state, field); }); document.addEventListener('click', function (event) { if (!event.target.closest('.mac-inline-filter-field')) { panel.querySelectorAll('.mac-inline-filter-popup.open').forEach(function (item) { item.classList.remove('open'); }); } }); submitButton.addEventListener('click', async function () { var results = []; for (var h = 0; h <= 9; h += 1) { for (var t = 0; t <= 9; t += 1) { for (var o = 0; o <= 9; o += 1) { if (!matches(state, h, t, o)) continue; results.push('' + h + t + o); } } } var resultStates; try { var payload = await ensureLatestDrawPayload(); resultStates = analyzeResultConnectivity(results, payload); } catch (error) { console.error('result connectivity failed', error); resultStates = buildResultTagMap(results).map(function (item) { return { value: item.value, tag: item.tag, canConnect: false, matchedRefs: [], lines: [], }; }); } var connectCount = resultStates.filter(function (item) { return item.canConnect; }).length; resultCount.textContent = '共 ' + results.length + ' 个 / 可连 ' + connectCount + ' 个'; resultText.value = buildResultText(results); syncResultHeight(); saveState(state); renderResultStates(resultStates); renderLinesForResults(resultStates); }); resetButton.addEventListener('click', function () { state = createState(); saveState(state); renderLinesForResults([]); panel.remove(); mountPanel(); }); copyButton.addEventListener('click', async function () { var text = resultText.value || ''; if (!text.trim()) return; try { await navigator.clipboard.writeText(text); } catch (error) { resultText.focus(); resultText.select(); document.execCommand('copy'); } copyButton.textContent = '已拷贝'; window.setTimeout(function () { copyButton.textContent = '拷贝'; }, 1200); }); syncResultHeight(); resultText.addEventListener('input', syncResultHeight); syncLatestSummary(); if (mountTarget.anchor && mountTarget.anchor.nextSibling) { mountTarget.parent.insertBefore(panel, mountTarget.anchor.nextSibling); } else if (mountTarget.anchor) { mountTarget.parent.appendChild(panel); } else { mountTarget.parent.appendChild(panel); } return true; } function boot() { if (mountPanel()) return; var observer = new MutationObserver(function () { if (mountPanel()) { observer.disconnect(); } }); observer.observe(document.documentElement, { childList: true, subtree: true }); window.setTimeout(mountPanel, 600); window.setTimeout(mountPanel, 1500); window.setTimeout(mountPanel, 3000); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', boot, { once: true }); } else { boot(); } })();