// ==UserScript== // @name 公众平台助手 // @namespace http://tampermonkey.net/ // @version 0.1 // @description 增加小程序公众平台的快捷键,方便操作 // @author Kuohao-wu // @match https://mp.weixin.qq.com/wx* // @icon https://www.google.com/s2/favicons?sz=64&domain=qq.com // @installURL https://quickapp-novel-image.oss-cn-shenzhen.aliyuncs.com/env_dev/temp_dir/%E5%85%AC%E4%BC%97%E5%B9%B3%E5%8F%B0%E5%8A%A9%E6%89%8B.user.js // @grant GM_addStyle // ==/UserScript== (function () { GM_addStyle(` #menu-container { position: fixed; bottom: 60px; right: 50px; background-color: #fff; /* 背景颜色 */ box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); /* 阴影 */ padding: 10px 14px; border-radius: 8px; z-index: 99; } /* 菜单项样式 */ #menu-list { list-style-type: none; padding: 0; font-size: 16px; } #menu-list li { margin-bottom: 10px; cursor:pointer; } #menu-list li { text-decoration: none; color: #333; /* 菜单文字颜色 */ } /* 菜单项 hover 样式 */ #menu-list li:hover { color: #007bff; /* 鼠标悬停时的文字颜色 */ } `); const viewMessage = () => { document.querySelector('[title="通知中心"]')?.click() } const viewDevManage = () => { document.querySelector('[href^="/wxamp/devprofile/get_profile"]')?.click() } const redirectTransaction = () => { document.querySelector('[href^="/wxamp/wacodepage"]')?.click() } const logout = () => { document.querySelector('[href^="/wxopen/walogout"]')?.click() } const changeAccount = () => { document.querySelector('[data-msgid="切换账号"]')?.click() createAccountSearch() const escHandler = (evt) => { if (evt.code === 'Escape') { document.querySelector('.switch_account_panel_header .close_icon').click() } } watchDialogVisible('.switch_account_dialog', { onShow() { window.addEventListener('keydown', escHandler) }, onHide() { window.removeEventListener('keydown', escHandler) } }) } function createAccountSearch() { const accountSearch = document.querySelector('#account-search') if (accountSearch) { setTimeout(() => { accountSearch.focus() }, 200) return } const accountSerarchInput = document.createElement('input') accountSerarchInput.id = 'account-search' accountSerarchInput.placeholder = '筛选账号' accountSerarchInput.type = 'text' accountSerarchInput.className = 'weui-desktop-form__input' accountSerarchInput.style.width = '450px' accountSerarchInput.style.borderRadius = '8px' accountSerarchInput.style.position = 'absolute' let isComposing = false; accountSerarchInput.addEventListener('compositionstart', () => { isComposing = true; }); accountSerarchInput.addEventListener('compositionend', (evt) => { isComposing = false; // 在这里执行你原本在input事件中进行的操作 filterAccountList(evt.target.value) }); accountSerarchInput.addEventListener('input', (evt) => { if (!isComposing) { // 非输入法输入时执行操作 filterAccountList(evt.target.value) } }); accountSerarchInput.addEventListener('keydown', (evt) => { console.log(evt.code) const targetList = document.querySelectorAll('.switch_account_dialog .account_list .account_item[data-visible="true"]') if (['NumpadEnter', 'Enter'].includes(evt.code) && targetList.length === 1) { console.log(targetList[0]) targetList[0]?.click() } }) const filterAccountList = (searchText) => { const list = document.querySelectorAll('.switch_account_dialog .account_list .account_item') const targetList = Array.from(list).filter(i => i.innerText.includes(searchText)) for (let item of list) { item.style.display = 'none' item.dataset['visible'] = 'false' } targetList.forEach(item => { item.style.display = 'flex' item.dataset['visible'] = 'true' }) } document.querySelector('.switch_account_panel_header > span').insertAdjacentElement('afterend', accountSerarchInput) setTimeout(() => { accountSerarchInput.focus() }, 200) } function watchDialogVisible(selector, { onShow, onHide }) { if (!document.querySelector(selector).style.display.includes('none')) return // 选择需要观察变动的节点 const targetNode = document.querySelector(selector); // 配置观察选项 const config = { attributes: true, attributeFilter: ['style'] }; let observer = null // 创建一个回调函数,当观察到变动时执行 const callback = function (mutationsList) { for (let mutation of mutationsList) { if (mutation.type === 'attributes') { if (targetNode.getAttribute(mutation.attributeName).includes('display: none')) { observer?.disconnect() console.log('dialog隐藏') if (typeof onHide === 'function') onHide() } else { console.log('dialog显示') if (typeof onShow === 'function') onShow() } } } }; // 创建一个观察器实例并传入回调函数 observer = new MutationObserver(callback); // 传入目标节点和观察选项 observer.observe(targetNode, config); } // 创建菜单容器 const menuContainer = document.createElement('div'); menuContainer.id = 'menu-container'; // 创建菜单列表 const menuList = document.createElement('ul'); menuList.id = 'menu-list'; menuList.style.listStyleType = 'none'; menuList.style.padding = '0'; // 菜单选项数组 const shotcutList = [ { key: 'ctrl+z', name: '查看消息(z)', handler: viewMessage }, { key: 'ctrl+b', name: '开发管理(b)', handler: viewDevManage }, { key: 'ctrl+x', name: '版本管理(x)', handler: redirectTransaction }, { key: 'ctrl+`', name: '切换账号(`)', handler: changeAccount }, { key: 'ctrl+q', name: '退出登录(q)', handler: logout } ] // 创建菜单选项并添加到菜单列表中 shotcutList.forEach((shotcut) => { const menuItem = document.createElement('li'); menuItem.textContent = shotcut.name; menuList.appendChild(menuItem); menuItem.addEventListener('click', shotcut.handler) }); // 将菜单列表添加到菜单容器中 menuContainer.appendChild(menuList); // 将菜单容器添加到页面 document.body.appendChild(menuContainer); document.addEventListener('keydown', function (event) { if (!event.ctrlKey) return shotcutList.forEach(item => { if (`ctrl+${event.key}` === item.key) { event.preventDefault(); item.handler() } }) }) })();