问题标题: 实现放大题干-更新!!

3
4
已解决
倪雨泽
倪雨泽
资深光能
资深光能

同学们,再也不用羡慕老师的放大题干功能啦!

相信各位都有羡慕老师端可以放大题干内容的想法。那么现在,你们可以不用羡慕啦~ 😊

我借助AI实现了一个油猴脚本,可以让我们在题库网站上实现类似的功能,点击按钮就能全屏显示题目内容,隐藏右侧的编辑器(左侧侧边栏保留)。快来试试吧!

油猴脚本代码

// ==UserScript==
// @name         酷丁编程题目全屏显示
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  在酷丁编程题目页面添加全屏显示题目内容的按钮
// @author       You
// @match        https://ke.kuding.cn/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 等待页面加载完成
    window.addEventListener('load', function() {
        // 查找题目求助按钮
        const helpButton = document.querySelector('button.el-button.el-tooltip.item.el-button--primary.el-button--mini.is-circle[aria-describedby]');

        if (helpButton) {
            // 创建全屏按钮
            const fullscreenButton = document.createElement('button');
            fullscreenButton.className = 'el-button el-button--primary el-button--mini is-circle';
            fullscreenButton.style.marginLeft = '0px';
            fullscreenButton.innerHTML = '<span>全</span>';
            fullscreenButton.title = '全屏显示题目内容';

            // 插入到求助按钮前面
            helpButton.parentNode.insertBefore(fullscreenButton, helpButton);

            // 添加点击事件
            fullscreenButton.addEventListener('click', function() {
                const rightContent = document.querySelector('.rightPproblemCotent');
                const leftContent = document.querySelector('.leftProblemCotent');

                if (rightContent && leftContent) {
                    if (rightContent.style.display === 'none') {
                        // 恢复显示
                        rightContent.style.display = '';
                        leftContent.style.width = '';
                        fullscreenButton.innerHTML = '<span>全</span>';
                    } else {
                        // 全屏显示
                        rightContent.style.display = 'none';
                        leftContent.style.width = '100%';
                        fullscreenButton.innerHTML = '<span>退</span>';
                    }
                }
            });
        }
    });
})();

 

使用方法

  1. 安装油猴扩展:如果你还没有安装油猴扩展,请先在浏览器中安装。油猴扩展是一个浏览器扩展,用于运行用户脚本。你可以从Tampermonkey官网下载并安装。
  2. 新建脚本:在油猴扩展中新建一个脚本。
  3. 粘贴代码:点击右上角的“复制代码”按钮,将上述代码粘贴到脚本编辑器中。
  4. 保存并启用:保存脚本并启用。

注意事项

  • 匹配规则@match 属性用于指定脚本运行的页面。此脚本仅在 酷丁编程 的页面上运行。

效果展示

  • 全屏显示:点击“全”按钮后,右侧编辑器将被隐藏,题目内容将全屏显示。
  • 退出全屏:再次点击“退”按钮,恢复原来的布局。
倪雨泽在2025-07-31 18:06:05追加了内容

sorry这边html不太能跑,劳烦同学们自己手动选择下复制啦

倪雨泽在2025-07-31 18:08:44追加了内容

 若同学们想实现绝对的全屏,可以再单击系统自带的收起侧边栏按钮

 

倪雨泽在2025-07-31 21:39:54追加了内容

又有了一个离谱的脚本_用字符模拟markdown

由于我之前发现朋友圈可以使用html,就将此时反映给了葛老师,老师也是瞬间就修复了。

然鹅,今天我突发奇想,能不能用油猴脚本使朋友圈支持markdown呢?

于是,我想到了将原编辑器替换为一个markdown编辑器(支持预览),然后将markdown转为html代码,最后显示。

So,我突然意识到,html好像已经因为我的反映而被禁了。。。。

于是乎,我就又突发奇想,想着能否通过哈希表模拟一个markdown捏.....

10 years later....

这个脚本就应声而起~

// ==UserScript==
// @name         酷丁编程朋友圈符号化Markdown(同步增强版)
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  实时同步Markdown内容到原编辑框,确保字数统计正常
// @author       You
// @match        https://ke.kuding.cn/*
// @grant        GM_addStyle
// @require      https://cdn.staticfile.org/jquery/3.7.1/jquery.min.js
// ==/UserScript==

(function() {
    'use strict';

    // 添加样式
    GM_addStyle(`
        .markdown-editor-container {
            margin-top: 10px;
            border: 1px solid #dcdfe6;
            border-radius: 4px;
        }
        .markdown-toolbar {
            display: flex;
            flex-wrap: wrap;
            gap: 5px;
            padding: 5px;
            background: #f5f5f5;
            border-bottom: 1px solid #dcdfe6;
        }
        .markdown-toolbar button {
            background: white;
            border: 1px solid #dcdfe6;
            border-radius: 3px;
            padding: 2px 8px;
            cursor: pointer;
            font-size: 14px;
        }
        .markdown-tabs {
            display: flex;
            margin-bottom: -1px;
        }
        .markdown-tab {
            padding: 5px 15px;
            background: #f5f5f5;
            border: 1px solid #dcdfe6;
            border-bottom: none;
            cursor: pointer;
            border-radius: 4px 4px 0 0;
            margin-right: 5px;
        }
        .markdown-tab.active {
            background: white;
            border-bottom: 1px solid white;
        }
        .markdown-textarea {
            width: 100%;
            min-height: 200px;
            padding: 10px;
            border: none;
            resize: vertical;
            font-family: monospace;
            box-sizing: border-box;
        }
        .markdown-preview {
            padding: 15px;
            min-height: 200px;
            background: white;
            display: none;
            white-space: pre-wrap;
            font-family: sans-serif;
        }
        .friends_item_content_text.processed {
            white-space: pre-wrap;
        }
    `);

    // 符号替换规则集(保持不变)
    const replacementRules = [
        { regex: /\*\*(.*?)\*\*/g, replacement: '【$1】' },
        { regex: /\*(.*?)\*/g, replacement: '/$1/' },
        { regex: /__(.*?)__/g, replacement: '【$1】' },
        { regex: /~~(.*?)~~/g, replacement: '~~$1~~' },
        { regex: /^#{6}\s(.*?)$/gm, replacement: '⑥ $1' },
        { regex: /^#{5}\s(.*?)$/gm, replacement: '⑤ $1' },
        { regex: /^#{4}\s(.*?)$/gm, replacement: '④ $1' },
        { regex: /^#{3}\s(.*?)$/gm, replacement: '③ $1' },
        { regex: /^#{2}\s(.*?)$/gm, replacement: '② $1' },
        { regex: /^#{1}\s(.*?)$/gm, replacement: '① $1' },
        { regex: /^- \s(.*?)$/gm, replacement: '• $1' },
        { regex: /^[0-9]+\. \s(.*?)$/gm, replacement: '⦿ $1' },
        { regex: /\\times/g, replacement: '×' },
        { regex: /\\div/g, replacement: '÷' },
        { regex: /\\plus/g, replacement: '+' },
        { regex: /\\minus/g, replacement: '-' },
        { regex: /\\equals/g, replacement: '=' },
        { regex: /\\sigma/g, replacement: 'Σ' },
        { regex: /\\pi/g, replacement: 'π' },
        { regex: /\\alpha/g, replacement: 'α' },
        { regex: /\\beta/g, replacement: 'β' },
        { regex: /_(\d+)/g, replacement: function(m, g) {
            const sub = {'0':'₀','1':'₁','2':'₂','3':'₃','4':'₄','5':'₅','6':'₆','7':'₇','8':'₈','9':'₉'};
            return g.split('').map(c => sub[c]).join('');
        }},
        { regex: /\^(\d+)/g, replacement: function(m, g) {
            const sup = {'0':'⁰','1':'¹','2':'²','3':'³','4':'⁴','5':'⁵','6':'⁶','7':'⁷','8':'⁸','9':'⁹'};
            return g.split('').map(c => sup[c]).join('');
        }},
        { regex: /^>\s(.*?)$/gm, replacement: '❝ $1' },
        { regex: /`(.*?)`/g, replacement: '「$1」' },
        { regex: /```(.*?)```/gs, replacement: '『$1』' }
    ];

    // 应用符号替换
    function applyReplacements(text) {
        let result = text;
        replacementRules.forEach(rule => {
            result = result.replace(rule.regex, rule.replacement);
        });
        return result;
    }

    // 核心改进:增强同步函数,触发多种事件确保原编辑框识别
    function syncToOriginal(originalTextarea, content) {
        if (!originalTextarea || !originalTextarea.length) return;

        // 1. 设置值(直接修改value属性,绕过表层监听)
        originalTextarea[0].value = content;

        // 2. 触发多种事件,确保字数统计更新(关键改进)
        const events = ['input', 'change', 'keyup', 'paste'];
        events.forEach(event => {
            const evt = new Event(event, { bubbles: true, cancelable: true });
            originalTextarea[0].dispatchEvent(evt);
        });

        // 3. 强制触发Vue/React等框架的双向绑定(如果页面使用框架)
        if (originalTextarea.data('v-model')) {
            originalTextarea.trigger('input');
        }
    }

    // 创建编辑器(强化同步逻辑)
    function createMarkdownEditor(originalTextarea) {
        const editorContainer = $('<div class="markdown-editor-container"></div>');
        const tabs = $(`
            <div class="markdown-tabs">
                <div class="markdown-tab active" data-tab="edit">编辑</div>
                <div class="markdown-tab" data-tab="preview">预览</div>
            </div>
        `);
        const toolbar = $(`
            <div class="markdown-toolbar">
                <button data-action="bold" title="粗体"><b>B</b></button>
                <button data-action="italic" title="斜体"><i>I</i></button>
                <button data-action="heading" title="标题">H</button>
                <button data-action="list" title="列表"></button>
                <button data-action="quote" title="引用"></button>
                <button data-action="code" title="代码">&lt;/&gt;</button>
                <button data-action="sub" title="下角标"></button>
                <button data-action="sup" title="上角标">¹</button>
                <button data-action="sigma" title="Σ">Σ</button>
                <button data-action="times" title="×">×</button>
            </div>
        `);
        const textarea = $('<textarea class="markdown-textarea" placeholder="使用Markdown格式编写内容..."></textarea>');
        const preview = $('<div class="markdown-preview"></div>');

        editorContainer.append(tabs, toolbar, textarea, preview);

        // 初始化:从原编辑框同步内容(确保初始状态一致)
        const initialContent = originalTextarea.val() || '';
        textarea.val(initialContent);
        updatePreview();

        // 标签切换
        tabs.on('click', '.markdown-tab', function() {
            const tab = $(this).data('tab');
            tabs.find('.markdown-tab').removeClass('active');
            $(this).addClass('active');
            textarea.toggle(tab === 'edit');
            preview.toggle(tab === 'preview');
        });

        // 工具栏操作(每次操作后立即同步)
        toolbar.on('click', 'button', function() {
            const action = $(this).data('action');
            const start = textarea[0].selectionStart;
            const end = textarea[0].selectionEnd;
            const text = textarea.val();
            let newText = '';
            let cursorPos = start;

            // 工具栏功能逻辑(保持不变)
            switch (action) {
                case 'bold':
                    newText = wrapSelection(text, start, end, '**', '**');
                    cursorPos = start + 2;
                    break;
                case 'italic':
                    newText = wrapSelection(text, start, end, '*', '*');
                    cursorPos = start + 1;
                    break;
                case 'heading':
                    newText = insertAtLineStart(text, start, '# ');
                    cursorPos = start + 2;
                    break;
                case 'list':
                    newText = insertAtLineStart(text, start, '- ');
                    cursorPos = start + 2;
                    break;
                case 'quote':
                    newText = insertAtLineStart(text, start, '> ');
                    cursorPos = start + 2;
                    break;
                case 'code':
                    newText = wrapSelection(text, start, end, '`', '`');
                    cursorPos = start + 1;
                    break;
                case 'sub':
                    newText = wrapSelection(text, start, end, '_', '');
                    cursorPos = end + 1;
                    break;
                case 'sup':
                    newText = wrapSelection(text, start, end, '^', '');
                    cursorPos = end + 1;
                    break;
                case 'sigma':
                    newText = insertText(text, start, end, '\\sigma');
                    cursorPos = start + 6;
                    break;
                case 'times':
                    newText = insertText(text, start, end, '\\times');
                    cursorPos = start + 6;
                    break;
            }

            textarea.val(newText);
            textarea[0].focus();
            textarea[0].setSelectionRange(cursorPos, cursorPos);
            updatePreview();
            syncToOriginal(originalTextarea, newText); // 操作后立即同步
        });

        // 辅助函数(保持不变)
        function wrapSelection(text, start, end, prefix, suffix) {
            const selected = text.substring(start, end);
            return text.substring(0, start) + prefix + selected + suffix + text.substring(end);
        }
        function insertAtLineStart(text, pos, insert) {
            const lineStart = text.lastIndexOf('\n', pos) + 1;
            return text.substring(0, lineStart) + insert + text.substring(lineStart);
        }
        function insertText(text, start, end, insert) {
            return text.substring(0, start) + insert + text.substring(end);
        }

        // 更新预览
        function updatePreview() {
            const markdown = textarea.val();
            preview.text(applyReplacements(markdown));
        }

        // 实时同步:监听输入事件,防抖处理避免频繁同步
        let syncDebounce;
        textarea.on('input', function() {
            const content = $(this).val();
            updatePreview();
            // 防抖:50ms内多次输入只同步一次,避免性能问题
            clearTimeout(syncDebounce);
            syncDebounce = setTimeout(() => {
                syncToOriginal(originalTextarea, content);
            }, 50);
        });

        // 双向同步:原编辑框内容变化时同步回Markdown编辑器
        originalTextarea.on('input', function() {
            const content = $(this).val();
            if (content !== textarea.val()) { // 避免循环同步
                textarea.val(content);
                updatePreview();
            }
        });

        return { container: editorContainer };
    }

    // 替换原始编辑器(优化元素定位)
    function replaceOriginalEditor() {
        const checkDialog = setInterval(() => {
            // 更精准的原编辑框定位:匹配带placeholder的文本框(通常是内容输入框)
            const dialog = $('.el-dialog__wrapper:visible');
            if (dialog.length === 0) return;

            // 查找可能的输入框(优先匹配带字数统计的场景)
            let originalTextarea = dialog.find('textarea[placeholder]');
            // 如果没找到,扩大范围(匹配所有文本框)
            if (originalTextarea.length === 0) {
                originalTextarea = dialog.find('textarea');
            }

            if (originalTextarea.length > 0 && !originalTextarea.data('markdown-replaced')) {
                clearInterval(checkDialog);
                originalTextarea.data('markdown-replaced', true).hide();
                const editor = createMarkdownEditor(originalTextarea);
                originalTextarea.after(editor.container);
            }
        }, 300); // 每300ms检查一次,确保对话框加载后立即处理
    }

    // 处理已发布内容(保持不变)
    function processExistingPosts() {
        $('.friends_item_content_text').each(function() {
            if (!$(this).data('processed')) {
                $(this).data('processed', true);
                const originalText = $(this).text();
                $(this).text(applyReplacements(originalText)).addClass('processed');
            }
        });
    }

    // 监听页面变化(保持不变)
    function observePosts() {
        const observer = new MutationObserver(mutations => {
            mutations.forEach(mutation => {
                if (mutation.addedNodes.length > 0) {
                    processExistingPosts();
                }
            });
        });
        const postsContainer = $('.friends_list')[0];
        if (postsContainer) {
            observer.observe(postsContainer, { childList: true, subtree: true });
        }
    }

    // 初始化
    $(function() {
        $(document).on('click', '.friends_title_btn2 button', function() {
            if ($(this).text().trim() === '发布') {
                setTimeout(replaceOriginalEditor, 300);
            }
        });
        processExistingPosts();
        observePosts();
    });
})();
倪雨泽在2025-07-31 21:46:43追加了内容

这个脚本就很抽象了

可以看见,原本的编辑器上覆盖了一个Markdown编辑器

那么我们该如何使用呢?

莫慌,你只需要像往常一样码Markdown即可,至于该编辑器是否支持(是否有这个代码的哈希),就听天由命咯~

 

.......

等待你们探索(虽然看脚本就能看出来还有哪些)

倪雨泽在2025-07-31 21:48:35追加了内容

上面示例的编辑区↑

倪雨泽在2025-07-31 21:49:20追加了内容

.

倪雨泽在2025-07-31 21:58:57追加了内容

油猴教程:https://zhuanlan.zhihu.com/p/128453110

倪雨泽在2025-07-31 22:10:10追加了内容

油猴拓展安装:https://www.crxsoso.com/webstore/detail/dhdgffkkebhmkfjojejmpbldmpobfkfo

倪雨泽在2025-08-01 11:38:51追加了内容

放大题干脚本下载:https://yuze-file.netlify.app/files/酷丁编程题目全屏显示-0.1.user.js

倪雨泽在2025-08-01 11:41:49追加了内容

朋友圈字符模拟markdown油猴脚本下载:https://yuze-file.netlify.app/files/酷丁编程朋友圈符号化Markdown(同步增强版)-1.2.user.js

倪雨泽在2025-08-01 11:45:10追加了内容

安装了篡改猴的同学,点击上面的两个链接应该会自动跳转到安装对应脚本页面,安装即可使用。

没安装篡改猴的同学点击上面我发的超链接“篡改猴”就可以自动下载了,如果支持则会自动安装到浏览器,反之需要同学们自己手动操作下。至于怎么操作,大家应该知道~

倪雨泽在2025-08-09 14:14:06追加了内容

发现了个BUG,针对题库里CF的题目,例如https://ke.kuding.cn/#/problem/problemJudgeDetail?id=5610 ,我的按钮会自动跑到

这是和脚本的检索方式有关系的,但是我没时间去更改了,大家是可以正常点击全屏的,不过退出就只能通过刷新(ctrl+r)了

倪雨泽在2025-08-13 10:46:24追加了内容

真正意义上的实现老师端功能

  • 受到该帖启发,本人用油猴脚本实现了自动化“开启老师权限”的功能。
  • 代码:
点击展开代码
// ==UserScript==
// @name         酷丁编程 - 全屏/缩小按钮切换
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  管理全屏和缩小按钮的显示状态,实现点击放大后隐藏放大按钮并显示缩小按钮
// @author       You
// @match        https://ke.kuding.cn/*
// @grant        none
// ==/UserScript==

(function() { 'use strict';

// 当前全屏状态
let isFullscreen = false;

// 主函数,查找并管理全屏/缩小按钮
function manageFullscreenButtons() {
    // 查找全屏按钮(放大镜图标)
    const fullscreenButton = document.querySelector('button.el-button--primary.el-button--mini.is-plain.is-circle .el-icon-zoom-in')?.closest('button');

    // 查找缩小按钮(缩小镜图标)
    const zoomOutButton = document.querySelector('button.el-button--primary.el-button--mini.is-plain.is-circle .el-icon-zoom-out')?.closest('button');

    // 初始化按钮状态
    if (fullscreenButton && zoomOutButton) {
        // 确保按钮可见
        fullscreenButton.style.display = isFullscreen ? 'none' : 'inline-block';
        zoomOutButton.style.display = isFullscreen ? 'inline-block' : 'none';

        // 添加全屏按钮点击事件(防止重复添加)
        if (!fullscreenButton.dataset.listenerAdded) {
            fullscreenButton.addEventListener('click', function() {
                enterFullscreen();
                fullscreenButton.style.display = 'none';
                zoomOutButton.style.display = 'inline-block';
            });
            fullscreenButton.dataset.listenerAdded = 'true';
        }

        // 添加缩小按钮点击事件(防止重复添加)
        if (!zoomOutButton.dataset.listenerAdded) {
            zoomOutButton.addEventListener('click', function() {
                exitFullscreen();
                zoomOutButton.style.display = 'none';
                fullscreenButton.style.display = 'inline-block';
            });
            zoomOutButton.dataset.listenerAdded = 'true';
        }
    }
}

// 进入全屏模式
function enterFullscreen() {
    console.log('进入全屏模式');
    isFullscreen = true;

    // 实际全屏逻辑 - 根据页面结构调整
    const rightContent = document.querySelector('.rightPproblemCotent');
    if (rightContent) {
        rightContent.style.width = '100%';
        rightContent.style.height = '100vh';
        rightContent.style.position = 'fixed';
        rightContent.style.top = '0';
        rightContent.style.left = '0';
        rightContent.style.zIndex = '9999';
        rightContent.style.backgroundColor = '#fff';
    }
}

// 退出全屏模式
function exitFullscreen() {
    console.log('退出全屏模式');
    isFullscreen = false;

    // 实际退出全屏逻辑 - 根据页面结构调整
    const rightContent = document.querySelector('.rightPproblemCotent');
    if (rightContent) {
        rightContent.style.width = '';
        rightContent.style.height = '';
        rightContent.style.position = '';
        rightContent.style.top = '';
        rightContent.style.left = '';
        rightContent.style.zIndex = '';
        rightContent.style.backgroundColor = '';
    }
}

// 初始执行
manageFullscreenButtons();

// 使用MutationObserver监听DOM变化
const observer = new MutationObserver(function(mutations) {
    manageFullscreenButtons();
});

// 开始观察整个文档
observer.observe(document, {
    childList: true,
    subtree: true
});

// 添加样式确保按钮图标可见
const style = document.createElement('style');
style.textContent = `
    button.el-button--primary.el-button--mini.is-plain.is-circle .el-icon-zoom-in,
    button.el-button--primary.el-button--mini.is-plain.is-circle .el-icon-zoom-out {
        display: inline-block !important;
    }
`;
document.head.appendChild(style);

})();

 

点击下载代码文件

  • 加载脚本后:
  • 点击放大后:

具体就等待同学们自己测试咯,是支持一切情况的,包括CF哦


1
已采纳
钱思源
钱思源
资深天翼
资深天翼

圈外人唯一的问题:为什么学科类只有语数外!!!我的最爱物理呢!!!!!!!!!

好歹照顾一下我们勤勤恳恳的初生啊

1
0
0
0
0
王子墨
王子墨
高级光能
高级光能

我的评价是不如双指滑动触摸板 doge

0
0
0
0
0
0
葛旻允
葛旻允
资深守护
资深守护

为什么我不行,但篡改猴显示已经启用了,多次刷新还是不行

0
孔巳辰
孔巳辰
高级光能
高级光能

窝巢,不是哥们~

but没啥用,只能装个币

0
刘煜熙
刘煜熙
新手守护
新手守护

我为啥不行呀,发个流程图/视频呗

0
0
我要回答