/** * 麦腾后台菜单爬虫脚本 * 用于自动探索和记录麦腾智能管理平台的所有菜单功能 * * 使用方法: * 1. 在浏览器中打开麦腾后台并登录 * 2. 打开浏览器开发者工具 (F12) * 3. 切换到 Console 标签 * 4. 复制粘贴此脚本并运行 * 5. 等待探索完成后,复制输出的 JSON 数据 */ class MaitengCrawler { constructor() { this.discoveredMenus = []; this.discoveredPages = []; this.visitedUrls = new Set(); this.delayBetweenActions = 1000; // 毫秒 } // 等待函数 async wait(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // 获取当前页面的菜单结构 getMenuStructure() { const menus = []; const menuItems = document.querySelectorAll('[role="menuitem"], .ant-menu-item, .menu-item'); menuItems.forEach((item, index) => { const menuInfo = { id: index, text: item.textContent?.trim() || '', element: item, href: item.querySelector('a')?.href || '', isExpanded: item.classList?.contains('expanded') || false, isCollapsed: item.classList?.contains('collapsed') || false, hasSubmenu: item.querySelector('ul, [role="menu"]') !== null }; if (menuInfo.text) { menus.push(menuInfo); } }); return menus; } // 获取当前页面信息 getCurrentPageInfo() { return { url: window.location.href, title: document.title, timestamp: new Date().toISOString(), pageElements: this.getPageElements() }; } // 获取页面关键元素 getPageElements() { const elements = { buttons: [], inputs: [], tables: [], filters: [] }; // 获取按钮 document.querySelectorAll('button, [role="button"]').forEach((btn, idx) => { elements.buttons.push({ id: idx, text: btn.textContent?.trim() || '', disabled: btn.disabled || false }); }); // 获取输入框 document.querySelectorAll('input, textarea, select').forEach((input, idx) => { elements.inputs.push({ id: idx, type: input.tagName?.toLowerCase() || '', placeholder: input.placeholder || '', name: input.name || '' }); }); // 获取表格 document.querySelectorAll('table').forEach((table, idx) => { elements.tables.push({ id: idx, rowCount: table.querySelectorAll('tr')?.length || 0 }); }); return elements; } // 尝试展开菜单 async expandMenu(menuElement) { try { menuElement.click(); await this.wait(this.delayBetweenActions); return true; } catch (error) { console.log('展开菜单失败:', error); return false; } } // 点击菜单项并记录页面 async clickMenuItem(menuItem) { try { if (menuItem.href && !menuItem.href.startsWith('javascript:')) { if (!this.visitedUrls.has(menuItem.href)) { this.visitedUrls.add(menuItem.href); window.location.href = menuItem.href; await this.wait(3000); // 等待页面加载 const pageInfo = this.getCurrentPageInfo(); this.discoveredPages.push(pageInfo); console.log('发现新页面:', pageInfo.title); // 返回上一页继续探索 window.history.back(); await this.wait(this.delayBetweenActions); } } else if (menuItem.element) { menuItem.element.click(); await this.wait(this.delayBetweenActions); const pageInfo = this.getCurrentPageInfo(); if (!this.visitedUrls.has(pageInfo.url)) { this.visitedUrls.add(pageInfo.url); this.discoveredPages.push(pageInfo); console.log('发现新页面:', pageInfo.title); } } return true; } catch (error) { console.log('点击菜单失败:', error); return false; } } // 主爬虫函数 async crawl() { console.log('🚀 开始麦腾后台菜单爬虫...'); console.log('当前页面:', window.location.href); // 获取初始菜单结构 const initialMenus = this.getMenuStructure(); console.log('发现菜单数量:', initialMenus.length); this.discoveredMenus = initialMenus; // 尝试展开所有可展开的菜单 for (const menu of initialMenus) { if (menu.isCollapsed && menu.hasSubmenu) { console.log('尝试展开菜单:', menu.text); await this.expandMenu(menu.element); } } // 重新获取展开后的菜单结构 const expandedMenus = this.getMenuStructure(); console.log('展开后菜单数量:', expandedMenus.length); this.discoveredMenus = expandedMenus; // 记录当前页面信息 const currentPage = this.getCurrentPageInfo(); this.discoveredPages.push(currentPage); this.visitedUrls.add(currentPage.url); console.log('\n✅ 爬虫完成!'); console.log('\n📊 发现的菜单:'); this.discoveredMenus.forEach((menu, idx) => { console.log(`${idx + 1}. ${menu.text} ${menu.isExpanded ? '[展开]' : menu.isCollapsed ? '[折叠]' : ''}`); }); console.log('\n📄 发现的页面:'); this.discoveredPages.forEach((page, idx) => { console.log(`${idx + 1}. ${page.title} - ${page.url}`); }); // 返回完整数据 return { menus: this.discoveredMenus.map(m => ({ text: m.text, href: m.href, isExpanded: m.isExpanded, isCollapsed: m.isCollapsed })), pages: this.discoveredPages.map(p => ({ url: p.url, title: p.title, timestamp: p.timestamp, buttons: p.pageElements.buttons.map(b => b.text), inputs: p.pageElements.inputs.map(i => i.placeholder || i.name) })) }; } // 导出数据为JSON exportToJSON() { const data = { crawlTime: new Date().toISOString(), menus: this.discoveredMenus, pages: this.discoveredPages }; const jsonStr = JSON.stringify(data, null, 2); console.log('\n📋 完整JSON数据:'); console.log(jsonStr); // 下载到文件 const blob = new Blob([jsonStr], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `maiteng-crawl-${Date.now()}.json`; a.click(); URL.revokeObjectURL(url); console.log('\n💾 JSON文件已下载!'); } } // 使用示例 console.log('=== 麦腾后台菜单爬虫 ==='); console.log('请运行: const crawler = new MaitengCrawler(); const result = await crawler.crawl(); crawler.exportToJSON();'); // 自动运行(可选) // (async () => { // const crawler = new MaitengCrawler(); // const result = await crawler.crawl(); // crawler.exportToJSON(); // })();