腾讯 Doc 大纲增强

腾讯 Doc 大纲操作增强,支持展开、折叠操作

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @license MIT
// @name         腾讯 Doc 大纲增强
// @namespace    http://tampermonkey.net/
// @version      2024-12-17
// @description  腾讯 Doc 大纲操作增强,支持展开、折叠操作
// @author       胡均
// @include      https://docs.qq.com/doc/*
// @grant        unsafeWindow
// @run-at       document-idle
// @icon         https://www.google.com/s2/favicons?sz=64&domain=google.com
// ==/UserScript==

(function() {
    'use strict';

    var expandLevel = function(level) {
        var margrinLeft = (level * 12) + 'px';
        //alert(margrinLeft);
        // 遍历控件
        var selElements = document.getElementsByClassName('headline-triangle');
        for (var i = 0; i < selElements.length; i++) {
            var nextSibling = selElements[i].nextElementSibling;
            if (nextSibling) {
                // 获取元素的计算样式,用于获取实际生效的样式值(包括继承等情况得到的最终值)
                var computedStyle = window.getComputedStyle(nextSibling);
                // 获取margin-left的样式值,返回的是带单位的字符串,例如 "20px"
                var marginLeftValue = computedStyle.getPropertyValue('margin-left');
                // 展开箭头的下一个控件是标题,每一级标题会左外边距+12px
                if(marginLeftValue == margrinLeft) {
                    // 模拟点击每个元素
                    selElements[i].click();
                }
            }
        }
    };

    // 展开所有目录
    var expandAll = function() {
        // 遍历控件
        var selElements = document.getElementsByClassName('headline-triangle');
        var oldSelElementsCnt = document.getElementsByClassName('headline-triangle').length;
        for (var i = 0; i < selElements.length; i++) {
            // 模拟点击每个元素
            selElements[i].click();
            // 点击后的目录节点总数
            var newSelElementsCnt = document.getElementsByClassName('headline-triangle').length;
            if(newSelElementsCnt < oldSelElementsCnt) {
                // 新的少于原来的,则代表有被折叠的,就把当前的重新点击一次展开
                selElements[i].click();
            } else {
                // 变多或不变,则代表展开目录或者没有下级目录
                console.log('展开或没有下级目录');
            }
        }
    };

    // 折叠所有目录
    var collapseAll = function() {
        // 遍历控件
        var selElements = document.getElementsByClassName('headline-triangle');
        let selElementsCnt = selElements.length;
        var oldSelElementsCnt = document.getElementsByClassName('headline-triangle').length;
        for (var i = selElementsCnt-1; i >= 0; i--) {
            // 模拟点击每个元素
            selElements[i].click();
            // 点击后的目录节点总数
            var newSelElementsCnt = document.getElementsByClassName('headline-triangle').length;
            if(newSelElementsCnt > oldSelElementsCnt) {
                // 新的少于原来的,则代表有被折叠的,就把当前的重新点击一次展开
                selElements[i].click();
            } else {
                // 变多或不变,则代表展开目录或者没有下级目录
                console.log('展开或没有下级目录');
            }
        }
    };

    // 展开按钮
    var btn_expand = document.createElement('button');
    btn_expand.textContent = '展开';
    btn_expand.style.padding = '3px 3px';
    btn_expand.style.backgroundColor = '#767676';
    btn_expand.style.color = 'white';
    btn_expand.style.border = 'none';
    btn_expand.style.borderRadius = '2px';
    btn_expand.addEventListener('click', function () {
        for(var i=0; i<=10; i++){
            expandAll();
        }
    });

    // 折叠按钮
    var btn_collapse = document.createElement('button');
    btn_collapse.textContent = '折叠';
    btn_collapse.style.padding = '3px 3px';
    btn_collapse.style.backgroundColor = '#767676';
    btn_collapse.style.color = 'white';
    btn_collapse.style.border = 'none';
    btn_collapse.style.borderRadius = '2px';
    btn_collapse.addEventListener('click', function () {
        for(var i=0; i<=10; i++){
            collapseAll();
        }
    });

    // 指定层级
    var inputElement = document.createElement('input');
    inputElement.type = 'text';
    inputElement.placeholder = '输入整数';
    inputElement.id = 'my_Input_Level';
    inputElement.style.width = '60px';
    inputElement.value = 3;

    // 展开到 N 级按钮
    var btn_expandLevel = document.createElement('button');
    btn_expandLevel.textContent = '展开到→级';
    btn_expandLevel.style.padding = '3px 3px';
    btn_expandLevel.style.backgroundColor = '#767676';
    btn_expandLevel.style.color = 'white';
    btn_expandLevel.style.border = 'none';
    btn_expandLevel.style.borderRadius = '2px';
    btn_expandLevel.addEventListener('click', function () {
        for(var i=0; i<=10; i++){
            // 全部展开才能实现折叠
            expandAll();
        }
        let inputVal = document.getElementById('my_Input_Level').value;
        let convertedValue = parseInt(inputVal);
        if (!isNaN(convertedValue)) {
            if(convertedValue <=0 || convertedValue >= 10) {
                inputElement.value = 1;
                expandLevel(1);
            } else {
                expandLevel(convertedValue);
            }
        } else {
            inputElement.value = 1;
            expandLevel(1);
        }
    });

    setTimeout(function(){
        // 设置大纲宽度
        var workbench_drawer_left = document.getElementById('workbench-drawer-left');
        if(workbench_drawer_left) {
            // 设置最小宽度,这里设置为 400px,你可以根据实际需求修改具体数值和单位
            workbench_drawer_left.style.minWidth = '400px';
            // 设置最大宽度,这里设置为 500px,同样可按需更改
            workbench_drawer_left.style.maxWidth = '400px';
        }

         // 添加大纲操作按钮
         // 1. 获取类名为 outline-title 的 div 元素,页面上显示为“大纲”两个字
         var targetDiv = document.getElementsByClassName('outline-title')[0];
         if (targetDiv) {
             // 2. 获取目标 div 元素的父节点
             var parentNode = targetDiv.parentNode;
             // 3. 使用 insertBefore 方法将按钮插入到目标 div 的下一个兄弟节点位置,
             // 如果目标 div 是父节点的最后一个子节点,那么按钮就会添加到最后成为新的最后一个子节点
             parentNode.insertBefore(inputElement, targetDiv.nextSibling);
             parentNode.insertBefore(btn_expandLevel, targetDiv.nextSibling);
             parentNode.insertBefore(btn_collapse, targetDiv.nextSibling);
             parentNode.insertBefore(btn_expand, targetDiv.nextSibling);
         }

        // 设置默认目录层级为 3 级
        expandLevel(3);
    }, 5000);
})();