// 知乎屏蔽词 - 选项页面脚本
(function () {
'use strict';
const input = document.getElementById('keyword-input');
const addBtn = document.getElementById('add-btn');
const listEl = document.getElementById('keyword-list');
const countEl = document.getElementById('count');
const statusEl = document.getElementById('status');
let keywords = [];
// 加载屏蔽词列表
async function loadKeywords() {
const result = await browser.storage.local.get('blockKeywords');
keywords = result.blockKeywords || [];
renderList();
}
// 保存屏蔽词列表
async function saveKeywords() {
await browser.storage.local.set({ blockKeywords: keywords });
}
// 渲染列表
function renderList() {
countEl.textContent = `共 ${keywords.length} 个屏蔽词`;
listEl.textContent = '';
if (keywords.length === 0) {
const tip = document.createElement('div');
tip.className = 'empty-tip';
tip.textContent = '暂无屏蔽词';
listEl.appendChild(tip);
return;
}
keywords.forEach((kw, index) => {
const item = document.createElement('div');
item.className = 'keyword-item';
const span = document.createElement('span');
span.className = 'keyword-text';
span.textContent = kw;
const btn = document.createElement('button');
btn.className = 'delete-btn';
btn.dataset.index = index;
btn.textContent = '删除';
item.appendChild(span);
item.appendChild(btn);
listEl.appendChild(item);
});
}
// 显示状态消息
function showStatus(message, isError = false) {
statusEl.textContent = message;
statusEl.className = 'status ' + (isError ? 'error' : 'success');
setTimeout(() => {
statusEl.className = 'status';
}, 2000);
}
// 添加屏蔽词
async function addKeyword() {
const keyword = input.value.trim();
if (!keyword) {
showStatus('请输入关键词', true);
return;
}
if (keywords.includes(keyword)) {
showStatus('该关键词已存在', true);
return;
}
keywords.push(keyword);
await saveKeywords();
renderList();
input.value = '';
showStatus('添加成功');
}
// 删除屏蔽词
async function deleteKeyword(index) {
keywords.splice(index, 1);
await saveKeywords();
renderList();
showStatus('删除成功');
}
// 导入屏蔽词
function importKeywords(file) {
const reader = new FileReader();
reader.onload = async function (e) {
const text = e.target.result.trim();
let incoming = [];
try {
const parsed = JSON.parse(text);
if (Array.isArray(parsed)) {
incoming = parsed.map(String).map(s => s.trim()).filter(Boolean);
} else {
showStatus('JSON 格式错误:需要数组', true);
return;
}
} catch {
// 非 JSON,按纯文本处理(每行一个关键词)
incoming = text.split('\n').map(s => s.trim()).filter(Boolean);
}
const existingSet = new Set(keywords);
const newWords = incoming.filter(w => !existingSet.has(w));
keywords.push(...newWords);
await saveKeywords();
renderList();
showStatus(`导入完成,新增 ${newWords.length} 个屏蔽词`);
};
reader.readAsText(file);
}
// 导出屏蔽词
function exportKeywords() {
const blob = new Blob([JSON.stringify(keywords, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'blocked_keywords.json';
a.click();
URL.revokeObjectURL(url);
}
// 事件监听
const importBtn = document.getElementById('import-btn');
const exportBtn = document.getElementById('export-btn');
const importFile = document.getElementById('import-file');
importBtn.addEventListener('click', () => importFile.click());
importFile.addEventListener('change', (e) => {
if (e.target.files.length > 0) {
importKeywords(e.target.files[0]);
e.target.value = '';
}
});
exportBtn.addEventListener('click', exportKeywords);
addBtn.addEventListener('click', addKeyword);
input.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
addKeyword();
}
});
listEl.addEventListener('click', (e) => {
if (e.target.classList.contains('delete-btn')) {
const index = parseInt(e.target.dataset.index, 10);
deleteKeyword(index);
}
});
// 初始化
loadKeywords();
})();