编辑
2025-04-16
DevOps
00

我有好几个集群,用 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>
如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:mereith

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!