Greasy Fork 还支持 简体中文。

米家极客版油猴插件

在极客页面中,点击设备列表,调用API获取设备和规则列表,并生成设备规则映射并显示在当前页面上

目前為 2024-05-19 提交的版本,檢視 最新版本

// ==UserScript==
// @name         米家极客版油猴插件
// @namespace    http://tampermonkey.net/
// @version      v0.1
// @description  在极客页面中,点击设备列表,调用API获取设备和规则列表,并生成设备规则映射并显示在当前页面上
// @author       王丰,sk163
// @license      MIT
// @match        http://*/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// ==/UserScript==
(async () => {
    const callAPI = (api, params) => {
        return new Promise(res => editor.gateway.callAPI(api, params, res));
    };

    const executeScript = async () => {
        if (typeof editor === 'undefined' || typeof editor.gateway === 'undefined' || typeof editor.gateway.callAPI === 'undefined') {
            console.error('editor.gateway.callAPI 方法未定义。请确保在正确的环境中运行此脚本。');
            return;
        }

        try {
            const devListResponse = await callAPI('getDevList');
            const devList = devListResponse.devList;
            const ruleList = await callAPI('getGraphList');
            let devRuleMap = {};

            for (const rule of ruleList) {
                const content = await callAPI('getGraph', { id: rule.id });
                const dids = new Set(content.nodes.map(n => n.props?.did).filter(d => d !== undefined));

                dids.forEach(d => {
                    devRuleMap[d] = devRuleMap[d] ?? [];
                    devRuleMap[d].push(rule.id);
                });
            }

            const result = Object.fromEntries(Object.entries(devRuleMap).map(([k, v]) => [
                devList[k]?.name ?? `did: ${k}`,
                v.map(r => ruleList.find(rr => rr.id === r).userData.name)
            ]));

            // 在当前页面上创建并显示结果
            const container = document.createElement('div');
            container.id = 'device-rule-map';
            container.style.position = 'fixed';
            container.style.top = '10px';
            container.style.right = '10px';
            container.style.width = '800px';
            container.style.maxHeight = '600px';
            container.style.overflowY = 'scroll';
            container.style.backgroundColor = 'white';
            container.style.border = '1px solid #ccc';
            container.style.padding = '10px';
            container.style.zIndex = 10000; // 确保在最上层显示
            container.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.1)';

            const closeButton = document.createElement('button');
            closeButton.textContent = '关闭';
            closeButton.style.position = 'absolute';
            closeButton.style.top = '5px';
            closeButton.style.right = '5px';
            closeButton.style.zIndex = 10001; // 确保在最上层显示
            closeButton.onclick = () => document.body.removeChild(container);

            container.innerHTML = `
                <h1 style="margin-top: 0;">设备规则映射结果</h1>
                <table border="1" cellspacing="0" cellpadding="5" style="width: 100%;">
                    <tr><th>设备</th><th>规则</th></tr>
                    ${Object.entries(result).map(([device, rules]) => `
                        <tr><td>${device}</td><td>${rules.join(', ')}</td></tr>
                    `).join('')}
                </table>
            `;
            container.appendChild(closeButton);
            document.body.appendChild(container);
        } catch (error) {
            console.error('调用 API 时出错:', error);
        }
    };

    // 检查初始的 hash 值
    if (window.location.hash === '#/device') {
        executeScript();
    }

    // 监听 hash 值变化
    window.addEventListener('hashchange', () => {
        if (window.location.hash === '#/device') {
            executeScript();
        }
    });
})();