使用油猴脚本让钉钉AI表格自动滚动

AI表格用来做任务管理还不错,还可以直接在大屏上展示,让大家都知道任务完成情况,但一旦任务多了,就展示不全了,需要滚动展示。

一开始的想法是直接用浏览器插件实现,但测试发现对AI表格是无效的,自动滚动插件是对整个页面进行自动滚动,而AI表格中的一条条数据是在一个框架内的,测试了多个插件都无效,那只能通过其他方式来实现了。

首先想到的就是油猴脚本了,毕竟AI时代,直接找AI写了,经历了多轮测试后,最终的脚本如下,对部分代码不清楚的或者油猴是什么怎么装的直接扔AI里解释。

// ==UserScript==
// @name         钉钉表格自动滚动(可调时间版)
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  可调整查找容器的时间
// @author       User
// @match        https://alidocs.dingtalk.com/aitable/share/view/*
// @match        https://alidocs.dingtalk.com/*
// @grant        none
// @run-at       document-idle
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const CONFIG = {
        scrollDelta: 200,
        interval: 1000,
        triggerTimes: 5,
        backToTopDelay: 3000,

        // ==================== 查找时间配置 ====================
        pageLoadWait: 1000,      // 页面已加载时的初始等待(毫秒)
        containerFindWait: 5000, // 查找容器的等待时间(毫秒)
        autoStartDelay: 2000,    // 自动启动延迟(毫秒)
        // ====================================================
    };

    let isRunning = false;
    let scrollTimer = null;
    let container = null;
    let isBackToTop = false;

    function log(msg) {
        console.log(`[钉钉滚动版] ${msg}`);
    }

    // 查找容器
    function findContainer() {
        var el = document.querySelector('.sc-1eczdly-0.bJJkUQ.GridViewAdapter.readonly');
        if (!el) {
            var allDivs = Array.prototype.slice.call(document.querySelectorAll('div'));
            var tallContainers = allDivs.filter(function(div) {
                return div.scrollHeight > div.clientHeight + 1000;
            });
            if (tallContainers.length > 0) el = tallContainers[0];
        }
        return el;
    }

    // 修复容器
    function fixContainer(container) {
        if (!container) return false;

        log('容器: ' + container.className);
        log('原始: ' + container.scrollHeight + '/' + container.clientHeight);

        container.style.cssText += `
            overflow-y: auto !important;
            overflow-x: hidden !important;
            position: relative !important;
            z-index: 9999 !important;
            height: 800px !important;
            max-height: 800px !important;
        `;

        container.offsetHeight;
        log('修复: ' + container.scrollHeight + '/' + container.clientHeight);

        return container.scrollHeight > container.clientHeight;
    }

    // 模拟滚轮
    function simulateWheel(element, deltaY) {
        const rect = element.getBoundingClientRect();
        const event = new WheelEvent('wheel', {
            deltaY: deltaY,
            bubbles: true,
            cancelable: true,
            view: window,
            clientX: rect.left + 100,
            clientY: rect.top + 100
        });
        element.dispatchEvent(event);

        if (element.parentElement) {
            element.parentElement.dispatchEvent(event);
        }
    }

    // 刷新页面
    function refreshPage(reason) {
        log('🔄 ' + reason + ',准备刷新页面...');
        log('3秒后刷新...');

        setTimeout(function() {
            log('正在刷新页面...');
            location.reload();
        }, 3000);
    }

    // 智能回到顶部
    function smartBackToTop() {
        return new Promise(function(resolve) {
            isBackToTop = true;
            log('🔄 开始回到顶部...');

            let attempts = 0;
            const maxAttempts = 30;
            const checkInterval = 100;

            const backTimer = setInterval(function() {
                attempts++;

                container.scrollTop = 0;
                simulateWheel(container, -CONFIG.backToTopSpeed);

                if (attempts % 3 === 0) {
                    simulateWheel(container, -CONFIG.backToTopSpeed * 2);
                }

                if (container.scrollTop <= 5) {
                    clearInterval(backTimer);
                    container.scrollTop = 0;
                    isBackToTop = false;
                    log('✅ 回到顶部完成');
                    resolve();
                } else if (attempts >= maxAttempts) {
                    clearInterval(backTimer);
                    container.scrollTop = 0;
                    isBackToTop = false;
                    log('⚠️ 强制回到顶部');
                    resolve();
                } else if (attempts % 5 === 0) {
                    log('回到顶部中... ' + container.scrollTop);
                }
            }, checkInterval);
        });
    }

    // 主滚动循环
    function mainScrollLoop() {
        if (!isRunning || isBackToTop) return;

        scrollTimer = setInterval(function() {
            if (!isRunning || isBackToTop) {
                clearInterval(scrollTimer);
                return;
            }

            simulateWheel(container, CONFIG.scrollDelta);

            // 到达底部检测 -直接刷新
            if (container.scrollTop + container.clientHeight >= container.scrollHeight - 10) {
                clearInterval(scrollTimer);
                refreshPage('到达底部');
                return;
            }

            // 进度提示
            if (Math.random() < 0.1) {
                var progress = ((container.scrollTop / container.scrollHeight) * 100).toFixed(1);
                log('滚动中... 进度: ' + progress + '%');
            }

        }, CONFIG.interval);
    }

    // 启动滚动
    function startScrolling() {
        if (isRunning || isBackToTop) {
            log('⚠️ 滚动已在运行或正在回到顶部');
            return;
        }

        isRunning = true;
        log('🚀 开始滚动 | 高度: ' + container.scrollHeight + '/' + container.clientHeight);

        let count = 0;
        let lastHeight = container.scrollHeight;

        // 第一阶段:触发加载
        const loadInterval = setInterval(function() {
            if (!isRunning || isBackToTop) {
                clearInterval(loadInterval);
                return;
            }

            simulateWheel(container, CONFIG.scrollDelta);
            count++;

            if (container.scrollHeight > lastHeight) {
                lastHeight = container.scrollHeight;
                log('✓ 数据加载中... 高度: ' + lastHeight);
            }

            if (count >= CONFIG.triggerTimes) {
                clearInterval(loadInterval);
                log('✓ 加载完成,开始正式滚动');
                mainScrollLoop();
            } else if (count % 2 === 0) {
                log('触发加载中... ' + count + '/' + CONFIG.triggerTimes);
            }
        }, 600);
    }

    // 切换滚动状态
    function toggleScroll() {
        if (!container) {
            log('❌ 容器未准备好');
            return;
        }

        if (isBackToTop) {
            log('⚠️ 正在回到顶部,请稍候');
            return;
        }

        if (isRunning) {
            isRunning = false;
            if (scrollTimer) {
                clearInterval(scrollTimer);
                scrollTimer = null;
            }
            log('⏸️ 滚动已停止,按S键继续');
        } else {
            log('▶️ 开始滚动');
            startScrolling();
        }
    }

    // 主函数
    function main() {
        log('脚本启动 - 可调时间版');
        log('查找时间配置:');
        log('  - 页面已加载等待: ' + CONFIG.pageLoadWait + 'ms');
        log('  - 容器查找等待: ' + CONFIG.containerFindWait + 'ms');
        log('  - 自动启动延迟: ' + CONFIG.autoStartDelay + 'ms');
        log('操作:S键控制启停,到达底部刷新');

        setTimeout(function() {
            container = findContainer();

            if (!container) {
                log('❌ 未找到容器');
                refreshPage('找不到容器');
                return;
            }

            if (fixContainer(container)) {
                log('✅ 容器准备就绪');
                // 自动启动
                setTimeout(function() {
                    if (!isRunning) {
                        log('▶️ 自动启动滚动');
                        startScrolling();
                    }
                }, CONFIG.autoStartDelay);

            } else {
                log('❌ 容器无法滚动');
                refreshPage('容器无法滚动');
            }
        }, CONFIG.containerFindWait);
    }

    // S键监听
    document.addEventListener('keydown', function(e) {
        if (e.key.toLowerCase() === 's') {
            e.preventDefault();
            toggleScroll();
        }
    });

    // 页面加载后执行
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', main);
    } else {
        setTimeout(main, CONFIG.pageLoadWait);
    }

})();

以上可实现,打开AI表格自动执行脚本,5秒后开始滚动,并可以设置滚动速度,滚动到底后自动刷新重新执行。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理