', {
text: '没有匹配选项',
class: 'bgm-dropdown-item',
css: { color: '#999', cursor: 'default' }
}).appendTo($dropdownContent);
}
};
// 将选项值插入到输入框
function insertOptionValue(inputElem, value) {
const text = inputElem.value;
const pos = inputElem.selectionStart;
const mode = inputElem.dataset.dropdownMode || 'append'; // 获取插入模式
const conn = inputElem.dataset.dropdownConnector || '、';
// 根据不同的插入模式处理
if (mode === 'replace') {
// 直接替换
inputElem.value = value;
} else if (mode === 'append') {
// 自动补全逻辑改进
if (text) {
const currentWord = text.slice(0, pos).toLowerCase();
if (value.toLowerCase().startsWith(currentWord)) {
// 如果当前输入是目标值的开头,直接替换整个值
inputElem.value = value + text.slice(pos);
inputElem.setSelectionRange(value.length, value.length);
inputElem.focus();
return;
}
// 处理分隔符和空格
const lastChar = text.slice(-1);
if (['、',',',',','+',' '].includes(lastChar)) {
// 如果最后一个字符是分隔符,直接添加新值
inputElem.value = text.trimRight() + value;
} else {
// 否则添加分隔符和新值
inputElem.value = text + conn + value;
}
} else {
// 如果输入框为空,直接设置值
inputElem.value = value;
}
}
inputElem.focus();
}
// 处理所有字段
const processAllFields = () => {
const $ = window.jQuery || window.$;
// 处理ID字段和对应的属性字段
$('input.inputtext.id').each(function() {
const $idInput = $(this);
const idValue = $idInput.val().trim();
const $propInput = $idInput.next('.inputtext.prop');
// 为空ID字段添加下拉菜单(如果配置了)
if (idValue === '' && config[''] && !$idInput.data('dropdownAdded')) {
createDropdown(this, config[''].options, config[''].mode);
}
// 为其他配置的字段添加下拉菜单
if ($propInput.length) {
Object.entries(config).forEach(([key, options]) => {
const keys = key.split(',').map(k => k.trim());
if (keys.includes(idValue) && !$propInput.data('dropdownAdded')) {
createDropdown($propInput[0], options.options, options.mode, options.connector);
}
});
}
});
};
// 处理动态添加的字段
const processDynamicField = (element) => {
const $ = window.jQuery || window.$;
const $element = $(element);
// 如果元素本身是输入框
if ($element.is('input.inputtext.id')) {
const $idInput = $element;
const idValue = $idInput.val().trim();
const $propInput = $idInput.next('.inputtext.prop');
// 空ID字段处理
if (idValue === '' && config['']) {
createDropdown($idInput[0], config[''].options, config[''].mode);
}
// 属性字段处理
if ($propInput.length) {
Object.entries(config).forEach(([key, options]) => {
const keys = key.split(',').map(k => k.trim());
if (keys.includes(idValue)) {
createDropdown($propInput[0], options.options, options.mode, options.connector);
}
});
}
}
// 如果元素是容器
else {
// 处理常规ID字段
$element.find('input.inputtext.id').each(function() {
const $idInput = $(this);
const idValue = $idInput.val().trim();
const $propInput = $idInput.next('.inputtext.prop');
// 空ID字段处理
if (idValue === '' && config['']) {
createDropdown($idInput[0], config[''].options, config[''].mode);
}
// 属性字段处理
if ($propInput.length) {
Object.entries(config).forEach(([key, options]) => {
const keys = key.split(',').map(k => k.trim());
if (keys.includes(idValue)) {
createDropdown($propInput[0], options.options, options.mode, options.connector);
}
});
}
});
}
};
// 初始化函数
const init = () => {
const $ = window.jQuery || window.$;
// 添加样式
injectStyles();
// 添加设置按钮
addSettingsButton();
// 初始处理所有字段
$(document).ready(function() {
processAllFields();
// 监听动态添加的字段
$(document).on('DOMNodeInserted', function(e) {
const $target = $(e.target);
if ($target.find('input.inputtext.id').length || $target.is('input.inputtext.id')) {
setTimeout(() => processDynamicField(e.target), 100);
}
});
// 点击页面其他位置时隐藏所有下拉框
$(document).on('click', function(e) {
if (!$(e.target).closest('.bgm-input-wrapper').length && !$(e.target).closest('.bgm-config-modal').length) {
$('.bgm-dropdown-content').removeClass('bgm-dropdown-active');
}
});
});
// 监听添加新行的按钮点击事件
$(document).on('click', '.newbtn', function() {
setTimeout(processAllFields, 100);
});
// 处理现有字段ID值变化的情况
$(document).on('change', 'input.inputtext.id', function() {
const $idInput = $(this);
const idValue = $idInput.val().trim();
const $propInput = $idInput.next('.inputtext.prop');
// 若属性字段已有下拉菜单,需要移除
if ($propInput.data('dropdownAdded')) {
if ($propInput.next('.bgm-dropdown-content').length) {
$propInput.next('.bgm-dropdown-content').remove();
}
$propInput.data('dropdownAdded', false);
// 如果输入框被包装了,尝试解包
if ($propInput.parent().hasClass('bgm-input-wrapper')) {
$propInput.unwrap();
}
}
// 添加新的下拉菜单
if ($propInput.length) {
Object.entries(config).forEach(([key, options]) => {
const keys = key.split(',').map(k => k.trim());
if (keys.includes(idValue)) {
createDropdown($propInput[0], options.options, options.mode, options.connector);
}
});
}
});
};
// 执行初始化
init();
}
/* =============
单行本快捷创建
===============*/
function addCreateButton() {
const currentPath = location.pathname;
// 只有精确匹配 /subject/数字 时才继续
const matchSubject = currentPath.match(/^\/subject\/(\d+)$/);
if (!matchSubject) return; // 如果不匹配,直接退出函数
// 确保作品类型是"小说"或"漫画"
const genreSmall = document.querySelector('small.grey');
if (!genreSmall || !(genreSmall.textContent === '小说' || genreSmall.textContent === '漫画')) return;
// 查找导航栏,并避免重复添加按钮
const nav = document.querySelector(".subjectNav .navTabs, .navTabs");
if (!nav || nav.querySelector(".create-button")) return;
// 创建"新条目"按钮并插入导航栏
const createLi = document.createElement("li");
createLi.className = "create-button";
const subjectId = matchSubject[1];
createLi.innerHTML = `
新条目`;
// 按钮点击事件:拉取编辑页信息并跳转到创建页
createLi.querySelector("a").addEventListener("click", () => {
const editUrl = `https://bangumi.tv/subject/${subjectId}/edit`;
const title = document.querySelector('h1 a[property="v:itemreviewed"]')?.textContent?.trim();
GM_xmlhttpRequest({
method: "GET",
url: editUrl,
onload: function (response) {
const parser = new DOMParser();
const doc = parser.parseFromString(response.responseText, "text/html");
const textarea = doc.querySelector('#subject_summary');
if (textarea) {
const content = textarea.value;
const type = content.includes("Infobox animanga/Novel") ? "Novel" :
content.includes("Infobox animanga/Manga") ? "Manga" : "Unknown";
// 如果无法识别类型则提示
if (type === "Unknown") {
alert("未识别 Infobox 类型(支持 Novel 或 Manga)");
return;
}
// 使用 localStorage 存储数据,并添加 subjectId 作为标识
const keyPrefix = `infobox_${subjectId}`;
localStorage.setItem(`${keyPrefix}_content`, content);
localStorage.setItem(`${keyPrefix}_type`, type);
localStorage.setItem(`${keyPrefix}_title`, title || '');
// 在新标签页打开新建条目页面,并传递 subjectId 参数
window.open(`https://bgm.tv/new_subject/1?source=${subjectId}`, "_blank");
} else {
alert("未找到 Infobox 内容,请确认已登录并有权限访问编辑页。");
}
},
onerror: function () {
// 请求失败时提示
alert("请求失败,请检查网络或登录状态。");
}
});
});
nav.appendChild(createLi); // 将按钮添加到导航栏
}
// 自动填充新建条目的表单内容
function fillNewSubjectForm() {
// 获取 URL 中传递的 source 参数,即当前条目的 subjectId
function getQueryParam(param) {
const url = new URL(window.location.href);
return url.searchParams.get(param);
}
const sourceId = getQueryParam("source");
if (!sourceId) return; // 如果没有传递 sourceId,则不执行填充操作
const keyPrefix = `infobox_${sourceId}`;
const content = localStorage.getItem(`${keyPrefix}_content`);
const type = localStorage.getItem(`${keyPrefix}_type`);
const originalTitle = localStorage.getItem(`${keyPrefix}_title`);
if (!content || !type) return; // 如果没有获取到 infobox 内容或类型,则不继续执行
// 定义类型与分类选项的映射
const typeMap = {
"Novel": { id: "cat_novel", tpl: "Novel" },
"Manga": { id: "cat_comic", tpl: "Manga" }
};
const category = typeMap[type];
if (!category) return;
// 选择对应的分类单选框
const radioBtn = document.getElementById(category.id);
if (radioBtn) {
radioBtn.click();
}
// 轮询检测表单是否加载完毕
const fillInterval = setInterval(() => {
const infobox = document.querySelector("#subject_infobox");
const titleInput = document.querySelector('input[name="subject_title"]');
const simpleModeLink = document.querySelector('a[onclick*="WCODEtoNormal"]');
// 当输入框加载完毕且可见,填充数据
if (infobox && titleInput && infobox.offsetParent !== null) {
infobox.value = content;
if (originalTitle) {
let newTitle = originalTitle;
const match = originalTitle.match(/\((\d+)\)$/);
if (match) {
const num = parseInt(match[1], 10) + 1;
newTitle = originalTitle.replace(/\(\d+\)$/, `(${num})`);
} else {
newTitle = `${originalTitle} (1)`;
}
titleInput.value = newTitle;
}
if (simpleModeLink) simpleModeLink.click(); // 切换回普通模式
clearInterval(fillInterval); // 停止轮询
// 填充完毕后删除 localStorage 中的数据,防止影响下次创建
localStorage.removeItem(`${keyPrefix}_content`);
localStorage.removeItem(`${keyPrefix}_type`);
localStorage.removeItem(`${keyPrefix}_title`);
}
}, 300); // 每 300ms 检查一次
}
// 若当前页面是创建条目页,绑定填充函数
if (location.pathname.includes("/new_subject/1")) {
window.addEventListener("load", fillNewSubjectForm);
}
/*===========
启动所有功能
============*/
function startEnhancer() {
initNavButtons();
observeURLChanges();
initCoverUpload();
initBatchRelation();
initBgmDropdownMenu();
addCreateButton();
console.log("Bangumi Ultimate Enhancer 已启动");
}
// 在DOM加载完成后启动脚本
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', startEnhancer);
} else {
startEnhancer();
}
})();