KJL后台-详情页直接显示自定义属性和参数
// ==UserScript==
// @name KJL后台-详情页直接显示自定义属性和参数
// @namespace Violentmonkey Scripts
// @match https://www.kujiale.com/pub/saas/brandgoods/detail?obsbrandgoodsid=*
// @grant none
// @version 1.0
// @author hejie13250
// @description 2025/3/11 12:43:21
// ==/UserScript==
(function() {
'use strict';
// 添加样式到文档
var style = document.createElement('style');
document.head.appendChild(style);
style.type = 'text/css';
style.appendChild(document.createTextNode(`
/* 隐藏右侧导航栏 */
.kduzNh { display: none; }
/* 改属性栏宽 */
.fOPLvQ {
position: relative;
flex: initial;
width: 50%;
max-width: 700px
}`));
let dataLoaded = false;
function addOptionItems() {
if (dataLoaded) return;
const targetSpan = document.querySelector('#obsBrandGoodsId > span:nth-child(2)');
if (!targetSpan) return;
dataLoaded = true;
observer.disconnect();
const obsBgId = targetSpan.textContent.trim();
// 合并两个API请求
Promise.allSettled([
fetch(`https://www.kujiale.com/editor/api/site/param/bizproperty/editordata/query?obsBrandGoodId=${obsBgId}`)
.then(r => r.json()),
fetch(`https://www.kujiale.com/dcscms/api/custom/brandgood/attribute?start=0&num=30&obsBgId=${obsBgId}`)
.then(r => r.json()),
fetch(`https://www.kujiale.com/editor/api/site/input/parameters/${obsBgId}`)
.then(r => r.json())
])
.then(responses => {
const container = document.querySelector('.fOPLvQ');
if (!container) return;
const tablesContainer = document.createElement('div');
tablesContainer.style.display = 'grid';
tablesContainer.style.gap = '40px';
responses.forEach((response, index) => {
if (response.status === 'fulfilled') {
const data = response.value;
if (index === 0 && data?.d) {
tablesContainer.appendChild(createTable('自定义输出属性',
data.d.map(item => ({
'属性名称': item.name,
'属性引用名': item.key,
'属性值': item.value
}))
));
} else if (index === 1 && data?.d?.result) {
tablesContainer.appendChild(createTable('自定义属性',
data.d.result.map(item => ({
'属性名称': item.attributeName,
'属性引用名': item.quoteName,
'属性值': item.attributeValue
}))
));
} else if (index === 2 && Array.isArray(data)) {
tablesContainer.appendChild(createTable('自定义参数',
data.map(item => ({
'参数名称': item.displayName,
'参数引用名': item.paramName
}))
));
}
} else {
console.error(`请求${index + 1}失败:`, response.reason);
}
});
if (tablesContainer.children.length > 0) {
container.insertAdjacentElement('afterend', tablesContainer);
}
});
}
// 创建通用表格创建函数
function createTable(title, data) {
const table = document.createElement('table');
table.style.cssText = 'width:100%; margin-top:20px; border-collapse:collapse;';
let columns;
if (data.length === 0) {
if (title === '自定义输出属性') {
columns = ['属性名称', '属性引用名', '属性值'];
} else if (title === '自定义属性') {
columns = ['属性名称', '属性引用名', '属性值'];
} else if (title === '自定义参数') {
columns = ['参数名称', '参数引用名'];
}
} else {
columns = Object.keys(data[0]);
}
const thead = document.createElement('thead');
thead.innerHTML = `<tr>${columns.map(col => `<th style="border:1px solid #ddd;padding:8px;">${col}</th>`).join('')}</tr>`;
const tbody = document.createElement('tbody');
data.forEach(item => {
const tr = document.createElement('tr');
tr.innerHTML = Object.values(item).map(val => `<td style="border:1px solid #ddd;padding:8px;">${val}</td>`).join('');
tbody.appendChild(tr);
});
table.appendChild(thead);
table.appendChild(tbody);
const wrapper = document.createElement('div');
wrapper.style.width = '100%';
wrapper.style.marginTop = '30px';
const titleEl = document.createElement('h3');
titleEl.textContent = title;
titleEl.style.cssText = 'font-size:16px; font-weight:bold; margin-bottom:10px;';
wrapper.appendChild(titleEl);
wrapper.appendChild(table);
return wrapper;
}
// 使用 MutationObserver 监听 DOM 变化
let observer = new MutationObserver(mutationsList => {
if (dataLoaded) return;
for (const mutation of mutationsList) {
if (mutation.type === 'childList' && document.querySelector('#obsBrandGoodsId > span:nth-child(2)')) {
addOptionItems();
// 删除 addOptionItems2 的调用
break;
}
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: false,
characterData: false
});
window.addEventListener('unload', () => {
observer.disconnect();
});
})();