我有好几个集群,用 PVE DataCenter Manager
管理的时候,发现跳转有 bug。
比如我用 https://pve.xxxx.com
(不用 8006 端口号),我在前端点 Open WebUI
跳转自动给我带上了 8006。
解法是登录到服务器,修改 /usr/share/javascript/proxmox-datacenter-manager/index.hbs
,在 head
标签下面加入这个 script
标签。
html <script type="text/javascript">
(function() {
// 判断字符串是否为IP地址
function isIPAddress(host) {
// IPv4地址正则表达式
const ipv4Pattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
if (!ipv4Pattern.test(host)) return false;
// 验证每个段是否在0-255范围内
const parts = host.split('.');
for (let i = 0; i < parts.length; i++) {
const part = parseInt(parts[i], 10);
if (part < 0 || part > 255) return false;
}
return true;
}
// 判断是否以.top结尾
function isTopDomain(host) {
return host.endsWith('.top');
}
// 移除8006端口号 - 修复正则表达式
function removePort8006(url) {
return url.replace(/:8006(\b|\/|#|\?)/, function(match, p1) {
return p1; // 保留分隔符但移除端口
});
}
// 处理URL函数
function processUrl(url) {
try {
const urlObj = new URL(url, window.location.href);
const host = urlObj.hostname;
console.log("处理URL:", url, "主机名:", host, "端口:", urlObj.port);
// 如果是IP地址,不做处理
if (isIPAddress(host)) {
console.log('IP地址链接,不做处理:', url);
return url;
}
// 如果不是.top域名,且有8006端口,去除端口号
if (!isTopDomain(host) && urlObj.port === '8006') {
const newUrl = removePort8006(url);
console.log('已移除端口号,新URL:', newUrl);
return newUrl;
}
return url;
} catch (e) {
console.error('解析URL时出错:', e);
return url;
}
}
// 立即覆盖window.open方法
const originalWindowOpen = window.open;
window.open = function(url, target) {
if (url) {
console.log("拦截到window.open调用:", url, target);
// 移除对target的检查,无论是否有target参数都处理
const newUrl = processUrl(url);
if (newUrl !== url) {
console.log("调用原始window.open,参数已修改:", newUrl, target);
return originalWindowOpen.call(this, newUrl, target || "_blank");
}
}
return originalWindowOpen.apply(this, arguments);
};
// 初始化其他拦截器
function initInterceptors() {
console.log("初始化拦截器...");
// 拦截所有链接点击事件
document.removeEventListener('click', linkClickHandler, true);
document.addEventListener('click', linkClickHandler, true);
// 拦截location.assign
const originalAssign = window.location.assign;
window.location.assign = function(url) {
console.log("拦截到location.assign调用:", url);
return originalAssign.call(window.location, processUrl(url));
};
// 尝试拦截location.href设置
try {
const originalLocationDescriptor = Object.getOwnPropertyDescriptor(Location.prototype, 'href');
if (originalLocationDescriptor && originalLocationDescriptor.configurable) {
Object.defineProperty(Location.prototype, 'href', {
set: function(url) {
console.log("拦截到location.href设置:", url);
return originalLocationDescriptor.set.call(this, processUrl(url));
},
get: originalLocationDescriptor.get,
configurable: true
});
}
} catch (e) {
console.error('拦截location.href失败:', e);
}
console.log("拦截器初始化完成");
}
// 链接点击处理函数
function linkClickHandler(event) {
// 查找事件路径中的链接元素
let element = event.target;
while (element && element.tagName !== 'A') {
element = element.parentElement;
if (!element) break;
}
// 如果找到链接
if (element && element.tagName === 'A') {
console.log("拦截到链接点击:", element.href, "target:", element.target);
const newUrl = processUrl(element.href);
if (newUrl !== element.href) {
event.preventDefault();
console.log("阻止默认操作,使用新URL打开:", newUrl);
if (element.target === '_blank') {
window.open(newUrl, '_blank');
} else {
window.location.href = newUrl;
}
}
}
}
// 添加MutationObserver以监视DOM变化
function setupMutationObserver() {
console.log("设置MutationObserver...");
const observer = new MutationObserver(function(mutations) {
// 当DOM变化时重新初始化拦截器
initInterceptors();
});
observer.observe(document.body, {
childList: true,
subtree: true
});
console.log("MutationObserver已设置");
}
// 初始化函数
function initialize() {
console.log("初始化拦截脚本...");
initInterceptors();
// DOM加载完成后设置MutationObserver
if (document.body) {
setupMutationObserver();
} else {
window.addEventListener('DOMContentLoaded', setupMutationObserver);
}
// 页面完全加载后再次初始化
window.addEventListener('load', function() {
console.log("页面加载完成,重新初始化拦截器");
initInterceptors();
// 延迟1秒再次初始化,确保WASM应用加载完成
setTimeout(initInterceptors, 1000);
});
console.log("拦截脚本初始化完成");
}
// 立即初始化
initialize();
// 添加到window对象,方便调试
window.__interceptorFunctions = {
initialize: initialize,
processUrl: processUrl,
isIPAddress: isIPAddress,
isTopDomain: isTopDomain,
removePort8006: removePort8006
};
})();
</script>
本文作者:mereith
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!