1Panel 增强

1Panel 功能增强

  1. // ==UserScript==
  2. // @name 1Panel 增强
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.11
  5. // @description 1Panel 功能增强
  6. // @author yuyan
  7. // @match *://*/*
  8. // @grant GM_setValue
  9. // @grant GM_getValue
  10. // @grant GM_registerMenuCommand
  11. // @grant GM_addStyle
  12. // @license MIT
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. // 配置项
  19. const CONFIG = {
  20. panelUrls: GM_getValue('panelUrls', []) // 存储用户配置的面板地址数组
  21. };
  22.  
  23. // 检查当前页面是否匹配配置的地址
  24. function isMatchingUrl() {
  25. if (!CONFIG.panelUrls.length) return false;
  26. const currentUrl = window.location.host; // 获取当前域名+端口
  27. return CONFIG.panelUrls.some(url => currentUrl.includes(url));
  28. }
  29.  
  30. // 添加样式
  31. GM_addStyle(`
  32. .panel-overlay {
  33. position: fixed;
  34. top: 0;
  35. left: 0;
  36. width: 100%;
  37. height: 100%;
  38. background: rgba(0, 0, 0, 0.5);
  39. z-index: 9998;
  40. display: none;
  41. }
  42.  
  43. .settings-panel {
  44. position: fixed;
  45. top: 50%;
  46. left: 50%;
  47. transform: translate(-50%, -50%);
  48. background: white;
  49. padding: 20px;
  50. border-radius: 8px;
  51. box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
  52. z-index: 9999;
  53. min-width: 400px;
  54. max-width: 600px;
  55. display: none;
  56. }
  57.  
  58. .settings-panel h2 {
  59. margin: 0 0 20px 0;
  60. padding-bottom: 10px;
  61. border-bottom: 1px solid #eee;
  62. }
  63.  
  64. .settings-content {
  65. max-height: 400px;
  66. overflow-y: auto;
  67. padding-right: 10px;
  68. }
  69.  
  70. .menu-item-control {
  71. margin-bottom: 10px;
  72. display: flex;
  73. align-items: center;
  74. }
  75.  
  76. .menu-item-control input[type="checkbox"] {
  77. margin-right: 10px;
  78. }
  79.  
  80. .panel-buttons {
  81. margin-top: 20px;
  82. text-align: right;
  83. border-top: 1px solid #eee;
  84. padding-top: 15px;
  85. }
  86.  
  87. .panel-button {
  88. padding: 8px 15px;
  89. margin-left: 10px;
  90. border: none;
  91. border-radius: 4px;
  92. cursor: pointer;
  93. }
  94.  
  95. .save-button {
  96. background: #409EFF;
  97. color: white;
  98. }
  99.  
  100. .cancel-button {
  101. background: #909399;
  102. color: white;
  103. }
  104.  
  105. .url-config {
  106. margin-bottom: 20px;
  107. padding: 15px;
  108. background: #f5f7fa;
  109. border-radius: 4px;
  110. }
  111.  
  112. .url-item {
  113. display: flex;
  114. gap: 10px;
  115. margin-bottom: 10px;
  116. }
  117.  
  118. .url-input {
  119. flex: 1;
  120. padding: 8px;
  121. border: 1px solid #dcdfe6;
  122. border-radius: 4px;
  123. }
  124.  
  125. .remove-url {
  126. background: #f56c6c;
  127. color: white;
  128. }
  129.  
  130. .add-url {
  131. background: #67c23a;
  132. color: white;
  133. width: 100%;
  134. }
  135.  
  136. .url-config p {
  137. margin: 5px 0;
  138. color: #909399;
  139. font-size: 12px;
  140. }
  141. `);
  142.  
  143. // 等待菜单元素加载
  144. function waitForMenu() {
  145. return new Promise(resolve => {
  146. const checkExist = setInterval(() => {
  147. const menu = document.querySelector('.el-menu--vertical');
  148. if (menu) {
  149. clearInterval(checkExist);
  150. resolve(menu);
  151. }
  152. }, 100);
  153. });
  154. }
  155.  
  156. // 获取菜单项文本
  157. function getMenuItemText(element) {
  158. const span = element.querySelector('span');
  159. return span ? span.textContent.trim() : '';
  160. }
  161.  
  162. // 创建菜单项控制
  163. function createMenuItemControl(text, isVisible) {
  164. const div = document.createElement('div');
  165. div.className = 'menu-item-control';
  166.  
  167. const checkbox = document.createElement('input');
  168. checkbox.type = 'checkbox';
  169. checkbox.checked = isVisible;
  170. checkbox.dataset.menuItem = text;
  171.  
  172. const label = document.createElement('label');
  173. label.textContent = text;
  174.  
  175. div.appendChild(checkbox);
  176. div.appendChild(label);
  177.  
  178. return div;
  179. }
  180.  
  181. // 创建URL配置面板
  182. function createUrlConfigPanel() {
  183. const overlay = document.createElement('div');
  184. overlay.className = 'panel-overlay';
  185.  
  186. const panel = document.createElement('div');
  187. panel.className = 'settings-panel';
  188. panel.innerHTML = `
  189. <h2>1Panel地址配置</h2>
  190. <div class="url-config">
  191. <div id="urlList">
  192. ${CONFIG.panelUrls.map((url, index) => `
  193. <div class="url-item">
  194. <input type="text" class="url-input" value="${url}">
  195. <button class="panel-button remove-url" data-index="${index}">删除</button>
  196. </div>
  197. `).join('')}
  198. </div>
  199. <button class="panel-button add-url" style="margin-top: 10px;">添加地址</button>
  200. <p>支持的格式:</p>
  201. <p>- 域名: panel.yourdomain.com</p>
  202. <p>- 域名带端口: panel.yourdomain.com:8888</p>
  203. <p>- IP: 192.168.1.100</p>
  204. <p>- IP带端口: 192.168.1.100:29758</p>
  205. </div>
  206. <div class="panel-buttons">
  207. <button class="panel-button cancel-button">取消</button>
  208. <button class="panel-button save-button">保存</button>
  209. </div>
  210. `;
  211.  
  212. overlay.appendChild(panel);
  213. document.body.appendChild(overlay);
  214. overlay.style.display = 'block';
  215. panel.style.display = 'block';
  216.  
  217. // 添加地址按钮事件
  218. panel.querySelector('.add-url').addEventListener('click', () => {
  219. const urlList = panel.querySelector('#urlList');
  220. const newUrlItem = document.createElement('div');
  221. newUrlItem.className = 'url-item';
  222. newUrlItem.innerHTML = `
  223. <input type="text" class="url-input" value="">
  224. <button class="panel-button remove-url">删除</button>
  225. `;
  226. urlList.appendChild(newUrlItem);
  227.  
  228. // 为新添加的删除按钮绑定事件
  229. newUrlItem.querySelector('.remove-url').addEventListener('click', function() {
  230. newUrlItem.remove();
  231. });
  232. });
  233.  
  234. // 为现有的删除按钮绑定事件
  235. panel.querySelectorAll('.remove-url').forEach(button => {
  236. button.addEventListener('click', function() {
  237. this.closest('.url-item').remove();
  238. });
  239. });
  240.  
  241. // 保存按钮事件
  242. panel.querySelector('.save-button').addEventListener('click', () => {
  243. const urls = Array.from(panel.querySelectorAll('.url-input'))
  244. .map(input => input.value.trim())
  245. .filter(url => url !== ''); // 过滤空值
  246.  
  247. GM_setValue('panelUrls', urls);
  248. CONFIG.panelUrls = urls;
  249. overlay.remove();
  250. alert('配置已保存,请刷新页面使配置生效');
  251. });
  252.  
  253. // 取消按钮事件
  254. panel.querySelector('.cancel-button').addEventListener('click', () => {
  255. overlay.remove();
  256. });
  257.  
  258. // 点击遮罩层关闭
  259. overlay.addEventListener('click', (e) => {
  260. if (e.target === overlay) {
  261. overlay.remove();
  262. }
  263. });
  264.  
  265. return { overlay, panel };
  266. }
  267.  
  268. // 创建设置面板HTML
  269. function createSettingsPanel() {
  270. const overlay = document.createElement('div');
  271. overlay.className = 'panel-overlay';
  272.  
  273. const panel = document.createElement('div');
  274. panel.className = 'settings-panel';
  275. panel.innerHTML = `
  276. <h2>菜单显示设置</h2>
  277. <div class="settings-content"></div>
  278. <div class="panel-buttons">
  279. <button class="panel-button cancel-button">取消</button>
  280. <button class="panel-button save-button">保存</button>
  281. </div>
  282. `;
  283.  
  284. overlay.appendChild(panel);
  285. document.body.appendChild(overlay);
  286.  
  287. return { overlay, panel };
  288. }
  289.  
  290. // 渲染设置面板内容
  291. async function renderSettings() {
  292. const menu = await waitForMenu();
  293. const settingsContent = document.querySelector('.settings-content');
  294. settingsContent.innerHTML = '';
  295.  
  296. const menuItems = menu.querySelectorAll('li');
  297. menuItems.forEach(item => {
  298. const text = getMenuItemText(item);
  299. if (text) {
  300. const saved = GM_getValue(text);
  301. const isVisible = saved === undefined ? true : saved;
  302. const control = createMenuItemControl(text, isVisible);
  303. settingsContent.appendChild(control);
  304. }
  305. });
  306. }
  307.  
  308. // 应用设置
  309. async function applySettings() {
  310. const menu = await waitForMenu();
  311. const menuItems = menu.querySelectorAll('li');
  312.  
  313. menuItems.forEach(item => {
  314. const text = getMenuItemText(item);
  315. if (text) {
  316. const isVisible = GM_getValue(text, true);
  317. item.style.display = isVisible ? '' : 'none';
  318. }
  319. });
  320. }
  321.  
  322. // 保存设置
  323. function saveSettings() {
  324. const controls = document.querySelectorAll('.menu-item-control input');
  325. controls.forEach(checkbox => {
  326. const text = checkbox.dataset.menuItem;
  327. GM_setValue(text, checkbox.checked);
  328. });
  329. applySettings();
  330. }
  331.  
  332. // 显示设置面板
  333. function showSettingsPanel() {
  334. const { overlay, panel } = createSettingsPanel();
  335. overlay.style.display = 'block';
  336. panel.style.display = 'block';
  337. renderSettings();
  338.  
  339. // 注册(不可用)事件处理
  340. panel.querySelector('.save-button').addEventListener('click', () => {
  341. saveSettings();
  342. overlay.remove();
  343. });
  344.  
  345. panel.querySelector('.cancel-button').addEventListener('click', () => {
  346. overlay.remove();
  347. });
  348.  
  349. overlay.addEventListener('click', (e) => {
  350. if (e.target === overlay) {
  351. overlay.remove();
  352. }
  353. });
  354. }
  355.  
  356. // 初始化
  357. function init() {
  358. // 注册(不可用)URL配置菜单
  359. GM_registerMenuCommand('⚙️ 配置1Panel地址', createUrlConfigPanel);
  360.  
  361. // 只在匹配的URL下执行面板功能
  362. if (isMatchingUrl()) {
  363. // 注册(不可用)菜单命令
  364. GM_registerMenuCommand('📋 菜单显示设置', showSettingsPanel);
  365.  
  366. // 应用已保存的设置
  367. applySettings();
  368. }
  369. }
  370.  
  371. // 启动脚本
  372. init();
  373. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址