// ==UserScript==
// @name PoEDB 雕像词缀中英对照
// @namespace http://tampermonkey.net/
// @version 1.1
// @description 在 PoEDB 页面缓存 `us` 词缀,适用于所有 `非 us` 语言页面,支持高级搜索模式(AND/OR 复合查询)并高亮搜索词。
// @author 开始摸鱼
// @match https://poedb.tw/*_Idol
// @run-at document-end
// @grant none
// @license MIT
// @downloadURL https://update.greasyfork.icu/scripts/528210/PoEDB%20%E9%9B%95%E5%83%8F%E8%AF%8D%E7%BC%80%E4%B8%AD%E8%8B%B1%E5%AF%B9%E7%85%A7.user.js
// @updateURL https://update.greasyfork.icu/scripts/528210/PoEDB%20%E9%9B%95%E5%83%8F%E8%AF%8D%E7%BC%80%E4%B8%AD%E8%8B%B1%E5%AF%B9%E7%85%A7.meta.js
// ==/UserScript==
(function () {
'use strict';
console.log("🔍 [PoEDB 词缀中英对照] 脚本启动...");
const lang = document.documentElement.lang;
const targetLang = "us";
const supportedLangs = ["cn", "tw", "kr", "jp", "fr", "de", "es", "ru", "th", "pt"];
const isSupportedLang = supportedLangs.includes(lang);
if (!isSupportedLang && lang !== "us") {
return;
}
const highlightColors = ["#ffff99", "#99ff99", "#99ccff", "#ff9999", "#ffcc66"]; // 预定义高亮颜色组
const uiContainer = document.createElement("div");
uiContainer.style.position = "fixed";
uiContainer.style.top = "10px";
uiContainer.style.right = "10px";
uiContainer.style.zIndex = "9999";
uiContainer.style.background = "#fff";
uiContainer.style.color = "#333";
uiContainer.style.border = "1px solid #ccc";
uiContainer.style.padding = "8px";
uiContainer.style.borderRadius = "6px";
uiContainer.style.boxShadow = "0px 0px 10px rgba(0,0,0,0.1)";
uiContainer.style.fontSize = "14px";
uiContainer.style.textAlign = "center";
document.body.appendChild(uiContainer);
const searchInput = document.createElement("input");
searchInput.type = "text";
searchInput.placeholder = "🔍 搜索词缀...";
searchInput.style.width = "100%";
searchInput.style.marginBottom = "6px";
searchInput.style.padding = "4px";
searchInput.style.border = "1px solid #ccc";
searchInput.style.borderRadius = "4px";
searchInput.addEventListener("input", () => {
filterMods(searchInput.value.trim());
});
uiContainer.appendChild(searchInput);
if (lang === "us") {
const saveBtn = document.createElement("button");
saveBtn.textContent = "保存 `us` 版数据";
saveBtn.style.display = "block";
saveBtn.style.marginBottom = "6px";
saveBtn.addEventListener("click", () => {
savePageData();
alert("✅ `us` 页面数据已保存!请切换到其他语言版本查看对照翻译。");
});
uiContainer.appendChild(saveBtn);
}
if (isSupportedLang) {
const toggleTranslateBtn = document.createElement("button");
toggleTranslateBtn.textContent = "加载对照翻译";
toggleTranslateBtn.style.display = "block";
toggleTranslateBtn.style.marginBottom = "6px";
toggleTranslateBtn.addEventListener("click", () => {
if (toggleTranslateBtn.textContent === "加载对照翻译") {
loadTranslation();
toggleTranslateBtn.textContent = "移除对照翻译";
} else {
removeTranslation();
toggleTranslateBtn.textContent = "加载对照翻译";
}
});
uiContainer.appendChild(toggleTranslateBtn);
}
const clearCacheBtn = document.createElement("button");
clearCacheBtn.textContent = "清除缓存";
clearCacheBtn.style.display = "block";
clearCacheBtn.addEventListener("click", () => {
// 遍历localStorage中的所有键
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
// 检查键是否包含_Idol
if (key.includes('_Idol')) {
// 删除符合条件的缓存项
localStorage.removeItem(key);
console.log(`已清除缓存项: ${key}`);
}
}
alert("🗑 `us` 版缓存已清除!");
});
uiContainer.appendChild(clearCacheBtn);
function savePageData() {
let modData = {};
document.querySelectorAll(".mod-title.explicitMod").forEach(element => {
const bsTarget = element.getAttribute("data-bs-target");
if (bsTarget) {
const modId = bsTarget.replace("#", "");
let modText = element.cloneNode(true);
modText.querySelectorAll(".float-end").forEach(span => span.remove());
modText = modText.innerText.trim();
modData[modId] = modText;
}
});
var currentUrl = window.location.href;
const urlParts = currentUrl.split('/');
const lastPart = urlParts[urlParts.length - 1];
localStorage.setItem(lastPart, JSON.stringify(modData));
console.log("✅ [PoEDB] `us` 页面数据已缓存:", modData);
}
function loadTranslation() {
var currentUrl = window.location.href;
const urlParts = currentUrl.split('/');
const lastPart = urlParts[urlParts.length - 1];
const savedData = localStorage.getItem(lastPart);
if (!savedData) {
alert("⚠️ 你还没有保存 `us` 版页面内容,请先切换到 `us` 页面并点击保存。");
return;
}
let modData = JSON.parse(savedData);
let matchedCount = 0;
document.querySelectorAll(".mod-title.explicitMod").forEach(element => {
const bsTarget = element.getAttribute("data-bs-target");
if (bsTarget) {
const modId = bsTarget.replace("#", "");
if (modData[modId]) {
const cnText = element.cloneNode(true);
cnText.querySelectorAll(".float-end").forEach(span => span.remove());
const cnTextOnly = cnText.innerText.trim();
const usText = modData[modId];
const translationSpan = document.createElement("span");
translationSpan.style.color = "gray";
translationSpan.style.fontSize = "0.9em";
translationSpan.classList.add("us-translation");
translationSpan.innerHTML = `
${usText}`;
element.appendChild(translationSpan);
matchedCount++;
}
}
});
if (matchedCount <= 0) {
alert("❌ 没有匹配的 `us` 词缀,请确认 `us` 版本已正确保存。");
}
}
function removeTranslation() {
document.querySelectorAll(".us-translation").forEach(el => el.remove());
}
function highlightText(text, terms) {
let highlighted = text;
terms.forEach((group, index) => {
const color = highlightColors[index % highlightColors.length];
group.forEach(term => {
const regex = new RegExp(`(${term})`, "gi");
highlighted = highlighted.replace(regex, `$1`);
});
});
return highlighted;
}
function filterMods(keyword) {
if (!keyword) {
document.querySelectorAll(".mod-title.explicitMod").forEach(element => {
element.style.display = "";
element.innerHTML = element.getAttribute("data-original-text") || element.innerHTML;
});
return;
}
const orGroups = keyword.split(" ").map(group => group.split(" "));
document.querySelectorAll(".mod-title.explicitMod").forEach(element => {
const text = element.innerText;
const match = orGroups.some(andTerms => andTerms.every(term => text.includes(term)));
if (match) {
element.style.display = "";
if (!element.hasAttribute("data-original-text")) {
element.setAttribute("data-original-text", element.innerHTML);
}
element.innerHTML = highlightText(element.getAttribute("data-original-text"), orGroups);
} else {
element.style.display = "none";
}
});
}
})();