轻量、安全、易用的HTML测试运行预览工具(修改)

轻量、安全、易用的HTML测试运行预览工具(修改)

修改后的版本更加灵活!可视化控制台面板会捕获 console.log、info、warn 的输出,并实时显示。内置帮助。
该工具不依赖任何后端服务——不需要联网,所有代码解析、渲染、帮助文档均内嵌在HTML文件中。您可以下载该文件,在离线环境下直接用浏览器打开,所有功能正常工作。
唯一的例外是:如果您的代码中引用了外部网络资源(如图片、CDN脚本),预览时自然需要网络加载这些资源,但工具本身与网络无关。

介绍

轻量、安全、易用的HTML代码测试运行工具,核心价值在于:

  ·  零依赖(纯 HTML/CSS/JS 实现,无需后端);

  ·  沙箱隔离保障运行安全;

  ·  开箱即用的示例代码,降低使用门槛。

  ·  这是一个纯前端工具,所有代码处理、预览和帮助功能都在您的浏览器中本地完成。

使用方法

左右分栏:左侧代码编辑器,右侧沙箱预览。在编辑器中输入代码。点击“运行”按钮或 Ctrl+Enter 立即预览渲染结果——渲染出网页的样子。

几点说明

智能代码识别:自动区分纯JS、纯CSS、HTML片段或完整页面,无需手动添加<script><style>标签,直接输入代码即可预览。

代码编辑与实时预览:页面采用左右分栏布局。左侧是代码编辑器,您可以直接编写HTML、CSS或JavaScript代码。右侧是预览面板,点击“运行代码”按钮后,代码会在一个沙箱隔离的iframe中渲染,确保运行环境安全,不会影响主页面。

状态反馈与快捷操作:顶部工具栏会清晰显示运行状态(如“就绪”、“渲染中”)。您可以使用Ctrl+Enter快捷键快速运行代码。工具栏上还提供了“重置示例” 按钮,方便您随时恢复内置的卡片示例代码。可视化控制台面板会捕获 console.log、info、warn 的输出,并实时显示。

清除功能:代码编辑器标题栏和工具栏都新增了“清除代码” 按钮。点击后,会清空左侧编辑器,并将右侧预览区替换为一个友好的空白引导页,提示您开始编写新代码。

运行截图及源码

运行截图:

源码(修改)如下:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>HTML运行器 - 安全沙箱预览</title>
    <style>
        * { box-sizing: border-box; }
        body {
            background: #1e1f2c;
            font-family: 'Segoe UI', 'Fira Code', monospace;
            margin: 0; padding: 20px; height: 100vh;
            display: flex; flex-direction: column;
        }
        .toolbar {
            background: #2d2f3e; border-radius: 16px; padding: 12px 20px;
            margin-bottom: 20px; display: flex; gap: 16px; align-items: center;
            flex-wrap: wrap; box-shadow: 0 4px 12px rgba(0,0,0,0.3);
        }
        .toolbar button {
            background: #4c6ef5; border: none; color: white; font-weight: bold;
            padding: 8px 24px; border-radius: 40px; font-size: 1rem;
            cursor: pointer; transition: 0.2s; font-family: inherit;
            box-shadow: 0 2px 5px rgba(0,0,0,0.2);
        }
        .toolbar button:hover { background: #5f7bf6; transform: scale(1.02); }
        .toolbar button:active { transform: scale(0.98); }
        .toolbar button.clear-btn { background: #e03e3e; }
        .toolbar button.clear-btn:hover { background: #f04a4a; }
        .toolbar button.help-btn { background: #8b5cf6; }
        .toolbar button.help-btn:hover { background: #a78bfa; }
        .toolbar span {
            color: #ccc; background: #1e1f2c; padding: 4px 12px;
            border-radius: 30px; font-size: 0.85rem;
        }
        .split-container {
            display: flex; flex: 1; gap: 20px; min-height: 0;
        }
        .editor-pane, .preview-pane {
            flex: 1; display: flex; flex-direction: column; border-radius: 20px;
            overflow: hidden; box-shadow: 0 8px 20px rgba(0,0,0,0.3);
        }
        .editor-pane { background: #282a36; }
        .editor-header, .preview-header {
            padding: 12px 16px; font-weight: 600;
            border-bottom: 1px solid #44475a;
        }
        .editor-header { background: #21222c; color: #bd93f9; }
        .preview-header { background: #f1f3f5; color: #2c3e66; display: flex; justify-content: space-between; align-items: center; }
        textarea {
            flex: 1; background: #282a36; color: #f8f8f2; border: none;
            padding: 20px; font-family: 'Fira Code', monospace; font-size: 14px;
            line-height: 1.5; resize: none; outline: none; tab-size: 4;
        }
        iframe { width: 100%; flex: 1; border: none; background: white; }
        .status-msg { font-size: 12px; background: #e9ecef; padding: 4px 12px; border-radius: 20px; color: #495057; }

        .modal-overlay {
            display: none;
            position: fixed; top: 0; left: 0; right: 0; bottom: 0;
            background: rgba(0,0,0,0.7); z-index: 1000;
            justify-content: center; align-items: center;
        }
        .modal-overlay.active { display: flex; }
        .modal-content {
            background: #2d2f3e; color: #e2e8f0; border-radius: 24px;
            max-width: 600px; width: 90%; max-height: 80vh; overflow-y: auto;
            padding: 32px; box-shadow: 0 20px 40px rgba(0,0,0,0.5);
            position: relative;
        }
        .modal-content h2 { color: #bd93f9; margin-top: 0; }
        .modal-content h3 { color: #f1c40f; margin-top: 24px; }
        .modal-content ul { padding-left: 20px; }
        .modal-content li { margin: 8px 0; line-height: 1.5; }
        .modal-content code {
            background: #1e1f2c; padding: 2px 6px; border-radius: 4px;
            font-family: 'Fira Code', monospace; color: #f8f8f2;
        }
        .modal-content .close-btn {
            position: absolute; top: 16px; right: 20px;
            background: none; border: none; color: #aaa; font-size: 28px;
            cursor: pointer; line-height: 1;
        }
        .modal-content .close-btn:hover { color: white; }
        .modal-content kbd {
            background: #44475a; padding: 2px 8px; border-radius: 6px;
            font-family: 'Fira Code', monospace; font-size: 0.9rem;
            border: 1px solid #6272a4;
        }
        @media (max-width: 700px) {
            .split-container { flex-direction: column; }
            body { padding: 12px; }
            .modal-content { padding: 24px; }
        }
    </style>
</head>
<body>
    <div class="toolbar">
        <button id="runBtn">▶ 运行代码</button>
        <button id="resetBtn">↺ 重置示例</button>
        <button id="clearBtn" class="clear-btn">🗑 清除代码</button>
        <button id="helpBtn" class="help-btn">❓ 帮助</button>
        <span>⚡ 安全沙箱 | 支持 HTML/CSS/JS</span>
        <span id="runtimeStatus" class="status-msg">就绪</span>
    </div>
    <div class="split-container">
        <div class="editor-pane">
            <div class="editor-header">📝 代码编辑器 (可编辑)</div>
            <textarea id="codeArea" spellcheck="false" placeholder="在这里编写 HTML/CSS/JS 代码..."></textarea>
        </div>
        <div class="preview-pane">
            <div class="preview-header">
                <span>🖥️ 实时预览 (沙箱隔离)</span>
                <span style="font-size:12px;">🔒 iframe sandbox</span>
            </div>
            <iframe id="previewFrame" sandbox="allow-same-origin allow-scripts allow-popups allow-forms allow-modals" title="代码预览"></iframe>
        </div>
    </div>

    <div id="helpModal" class="modal-overlay">
        <div class="modal-content">
            <button class="close-btn" id="closeHelpBtn">&times;</button>
            <h2>📘 使用帮助</h2>
            <p>欢迎使用HTML运行器!本工具提供一个<strong>安全的沙箱环境</strong>,让您即时预览HTML、CSS和JavaScript代码。</p>
            
            <h3>✨ 智能代码识别</h3>
            <ul>
                <li><strong>纯JS代码:</strong>直接输入 <code>alert('你好')</code> 或 <code>console.log('测试')</code> 等,会自动包裹 <code>&lt;script&gt;</code> 标签。console.log('测试')等控制台输出在预览区底部显示。</li>
                <li><strong>纯CSS代码:</strong>输入 <code>body { background: red; }</code> 会自动用 <code>&lt;style&gt;</code> 包裹并应用样式。</li>
                <li><strong>HTML片段:</strong>输入 <code>&lt;h1&gt;标题&lt;/h1&gt;</code> 或混合内容,会自动补全文档结构,并附带控制台面板。</li>
                <li><strong>完整HTML页面:</strong>如果代码以 <code>&lt;!DOCTYPE html&gt;</code> 或 <code>&lt;html&gt;</code> 开头,将保持原样渲染(不添加额外控制台面板)。</li>
            </ul>

            <h3>⚡ 快捷键</h3>
            <ul>
                <li><kbd>Ctrl</kbd> + <kbd>Enter</kbd> (Windows/Linux) 或 <kbd>Cmd</kbd> + <kbd>Enter</kbd> (Mac):快速运行代码。</li>
            </ul>

            <h3>🛠️ 功能按钮</h3>
            <ul>
                <li><strong>▶ 运行代码:</strong>将编辑器中的代码渲染到右侧预览区。</li>
                <li><strong>↺ 重置示例:</strong>恢复内置的欢迎页面示例。</li>
                <li><strong>🗑 清除代码:</strong>清空编辑器并显示空白提示页。</li>
                <li><strong>❓ 帮助:</strong>显示本帮助窗口。</li>
            </ul>

            <h3>🔒 安全说明</h3>
            <p>所有代码均在 <code>sandbox</code> 属性的iframe中运行,允许脚本、弹窗、表单等,但与主页面隔离,不会影响工具本身。</p>
        </div>
    </div>

    <script>
        const codeArea = document.getElementById('codeArea');
        const runBtn = document.getElementById('runBtn');
        const resetBtn = document.getElementById('resetBtn');
        const clearBtn = document.getElementById('clearBtn');
        const helpBtn = document.getElementById('helpBtn');
        const closeHelpBtn = document.getElementById('closeHelpBtn');
        const helpModal = document.getElementById('helpModal');
        const previewFrame = document.getElementById('previewFrame');
        const runtimeStatus = document.getElementById('runtimeStatus');

        // 改进的控制台面板:浅色背景、清晰可见、确保执行顺序
        const CONSOLE_INJECT = `
<div id="__console_panel" style="position:fixed;bottom:0;left:0;right:0;background:rgba(255,255,255,0.95);color:#1e293b;font-family:'Fira Code',monospace;font-size:13px;max-height:35%;overflow-y:auto;padding:10px 14px;z-index:99999;border-top:2px solid #cbd5e1;box-shadow:0 -4px 12px rgba(0,0,0,0.1);min-height:36px;">
    <div id="__console_placeholder" style="color:#94a3b8;">📋 控制台输出将显示在此处</div>
</div>
<script>
(function() {
    var panel = document.getElementById('__console_panel');
    var placeholder = document.getElementById('__console_placeholder');
    if (!panel) return;

    function addLog(level, args) {
        // 首次添加日志时移除占位提示
        if (placeholder) {
            placeholder.remove();
            placeholder = null;
        }
        var msg = args.map(function(a) {
            if (typeof a === 'object') {
                try { return JSON.stringify(a, null, 2); } catch(e) { return String(a); }
            }
            return String(a);
        }).join(' ');
        var entry = document.createElement('div');
        entry.style.margin = '3px 0';
        entry.style.padding = '2px 0';
        entry.style.borderBottom = '1px solid #e2e8f0';
        switch(level) {
            case 'error': entry.style.color = '#dc2626'; break;
            case 'warn': entry.style.color = '#d97706'; break;
            case 'info': entry.style.color = '#2563eb'; break;
            default: entry.style.color = '#1e293b';
        }
        entry.textContent = '[' + level.toUpperCase() + '] ' + msg;
        panel.appendChild(entry);
        panel.scrollTop = panel.scrollHeight;
    }

    var orig = {};
    ['log','info','warn','error','debug'].forEach(function(m) {
        orig[m] = console[m];
        console[m] = function() {
            addLog(m, Array.prototype.slice.call(arguments));
            orig[m].apply(console, arguments);
        };
    });

    window.addEventListener('error', function(e) {
        addLog('error', [e.message]);
    });
})();
<\/script>`;

        const DEFAULT_CODE = `<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>动态预览</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            background: linear-gradient(145deg, #f5f7fc 0%, #e9eef5 100%);
            display: flex; justify-content: center; align-items: center;
            min-height: 100vh; font-family: 'Segoe UI', Roboto, system-ui, sans-serif;
            padding: 20px;
        }
        .card {
            background: rgba(255,255,255,0.9); backdrop-filter: blur(10px);
            border-radius: 48px; padding: 32px 40px;
            box-shadow: 0 25px 45px rgba(0,0,0,0.15), 0 2px 5px rgba(0,0,0,0.05);
            text-align: center; max-width: 500px; transition: transform 0.2s;
            border: 1px solid rgba(255,255,255,0.5);
        }
        .card:hover { transform: scale(1.01); }
        h1 { color: #1e293b; margin-bottom: 16px; font-size: 2.2rem; }
        p { color: #334155; margin: 12px 0; line-height: 1.5; }
        button {
            background: #3b82f6; border: none; color: white; padding: 10px 28px;
            border-radius: 40px; font-size: 1rem; cursor: pointer; margin-top: 20px;
            transition: background 0.2s; font-weight: 500;
        }
        button:hover { background: #2563eb; }
        .highlight { background: #fef9c3; color: #854d0e; padding: 4px 12px; border-radius: 40px; display: inline-block; }
        footer { margin-top: 20px; font-size: 0.75rem; color: #64748b; }
    </style>
</head>
<body>
    <div class="card">
        <h1>✨ HTML运行器 ✨</h1>
        <p>恭喜!<span class="highlight">默认预览功能正常</span></p>
        <p>您可以编辑左侧代码,点击 <strong>▶ 运行代码</strong> 实时查看效果。</p>
        <button id="demoBtn">点我试试 (交互)</button>
        <footer>完全沙箱隔离 | 支持 JS/CSS/HTML</footer>
    </div>
    <script>
        document.getElementById('demoBtn')?.addEventListener('click', () => {
            alert('🎉 交互成功!您可以在编辑区写任何HTML/CSS/JS代码');
        });
    <\/script>
</body>
</html>`;

        function isLikelyCSS(code) {
            if (/\b(function|var|let|const|document|console|alert|=>|new |this\.|\.innerHTML|\.body)\b/.test(code)) return false;
            if (/[.#]?[a-zA-Z]+\s*\{[^}]*:[^}]*\}/.test(code)) return true;
            return false;
        }

        function runCode() {
            let code = codeArea.value;
            if (!code.trim()) {
                runtimeStatus.textContent = '⚠️ 代码为空,加载示例…';
                code = DEFAULT_CODE;
                codeArea.value = DEFAULT_CODE;
            }
            runtimeStatus.textContent = '⏳ 渲染中…';
            const trimmedCode = code.trim();
            const hasCompleteHTML = /<!DOCTYPE\s+html/i.test(trimmedCode) || /<html[\s>]/i.test(trimmedCode);
            const hasScriptTag = /<script[\s>]/i.test(trimmedCode);
            const startsWithHTML = /^\s*<[a-zA-Z!]/.test(code);

            try {
                if (!hasCompleteHTML && !hasScriptTag && !startsWithHTML) {
                    if (isLikelyCSS(code)) {
                        // CSS 自动包裹
                        code = `<!DOCTYPE html>
        <html lang="zh-CN">
        <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>CSS 预览</title><style>${code}</style></head>
        <body><div style="padding:2rem;color:#666;">✨ CSS 样式已应用(查看背景/布局变化)</div>${CONSOLE_INJECT}</body></html>`;
                        runtimeStatus.textContent = '🎨 检测到 CSS 代码,已用 <style> 包裹';
                    } else {
                        // JS 自动包裹:控制台注入在前,用户代码用 setTimeout 延迟执行确保劫持先生效
                        code = `<!DOCTYPE html>
        <html lang="zh-CN">
        <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>JS 预览</title></head>
        <body>${CONSOLE_INJECT}
        <script>
          setTimeout(function() {
            ${code}
          }, 0);
        <\/script></body></html>`;
                        runtimeStatus.textContent = '🔍 检测到纯JS代码,已自动包裹 <script>(控制台面板已启用)';
                    }
                } else if (!hasCompleteHTML) {
                    // HTML 片段:尝试将控制台注入放在最前面,但不能保证捕获所有同步脚本
                    if (!/meta\s+charset/i.test(code)) {
                        code = `<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>预览</title></head><body>${CONSOLE_INJECT}${code}</body></html>`;
                    } else {
                        code = `<!DOCTYPE html><html lang="zh-CN"><head><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>预览</title></head><body>${CONSOLE_INJECT}${code}</body></html>`;
                    }
                    runtimeStatus.textContent = '📄 HTML片段已补全文档结构(控制台面板已启用)';
                }
                // 完整HTML不做任何注入,保持原样

                const blob = new Blob([code], { type: 'text/html' });
                const url = URL.createObjectURL(blob);
                previewFrame.onload = () => {
                    URL.revokeObjectURL(url);
                    runtimeStatus.textContent = '✅ 预览已更新 (沙箱隔离)';
                };
                previewFrame.src = url;
            } catch (err) {
                console.error(err);
                runtimeStatus.textContent = '❌ 代码解析失败: ' + err.message;
                previewFrame.srcdoc = `<html><body style="background:#fff1f0;font-family:sans-serif;padding:2rem;"><h3>代码错误</h3><pre>${err.message}</pre></body></html>`;
            }
        }

        function resetExample() {
            codeArea.value = DEFAULT_CODE;
            runtimeStatus.textContent = '🔄 已重置示例,正在渲染…';
            runCode();
        }

        function clearCode() {
            codeArea.value = '';
            runtimeStatus.textContent = '🗑 代码已清除,预览区已清空';
            const emptyPageHTML = `<!DOCTYPE html>
        <html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>空白预览</title>
        <style>*{margin:0;padding:0;box-sizing:border-box;}body{background:#f8f9fa;display:flex;justify-content:center;align-items:center;min-height:100vh;font-family:'Segoe UI',sans-serif;color:#6c757d;}.empty-state{text-align:center;padding:40px;}.empty-state .icon{font-size:4rem;margin-bottom:20px;}.empty-state h2{font-size:1.5rem;margin-bottom:10px;color:#495057;}.empty-state p{font-size:0.95rem;line-height:1.6;}.empty-state .hint{margin-top:16px;padding:10px 20px;background:#e9ecef;border-radius:30px;font-size:0.85rem;display:inline-block;}</style></head>
        <body><div class="empty-state"><div class="icon">📝</div><h2>代码编辑区已清空</h2><p>请在左侧编辑器中编写 HTML/CSS/JS 代码,<br>然后点击 <strong>▶ 运行代码</strong> 查看效果。</p><span class="hint">💡 提示:点击 ↺ 重置示例 可恢复默认代码</span></div></body></html>`;
            try {
                const blob = new Blob([emptyPageHTML], { type: 'text/html' });
                const url = URL.createObjectURL(blob);
                previewFrame.onload = () => URL.revokeObjectURL(url);
                previewFrame.src = url;
            } catch (err) {
                previewFrame.srcdoc = emptyPageHTML;
            }
            codeArea.focus();
        }

        helpBtn.addEventListener('click', () => {
            helpModal.classList.add('active');
        });
        closeHelpBtn.addEventListener('click', () => {
            helpModal.classList.remove('active');
        });
        helpModal.addEventListener('click', (e) => {
            if (e.target === helpModal) helpModal.classList.remove('active');
        });

        codeArea.value = DEFAULT_CODE;
        runBtn.addEventListener('click', runCode);
        resetBtn.addEventListener('click', resetExample);
        clearBtn.addEventListener('click', clearCode);
        window.addEventListener('load', () => runCode());
        codeArea.addEventListener('keydown', (e) => {
            if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
                e.preventDefault();
                runCode();
            }
        });
    </script>
</body>
</html>

你可以试一试

测试用例

以下是测试代码,您可以直接复制到编辑器中运行,验证

直接输入JS代码或使用<script>包裹JS代码皆可

如:

alert('交互成功!您可以在编辑区写任何HTML/CSS/JS代码');

<script>
     alert('交互成功!您可以在编辑区写任何HTML/CSS/JS代码');
</script>

都可以。

②测试用例列表

编号

输入代码(粘贴到编辑器)

预期效果

测试重点

1

alert('你好,沙箱!')

弹出提示框

纯JS自动包裹:无需手动写<script>,系统应自动补全文档并执行

2

document.body.innerHTML = '<h1>动态生成</h1>';

页面显示大标题“动态生成”

纯JS操作DOM:验证JS对body的修改是否生效

3

console.log('测试消息');

console.info('这是一条 info 消息');

console.warn('这是一条 warn 警告');

控制台无输在预览区底部显示。

无界面JS:代码执行

4

body { background: tomato; }

页面背景变为番茄色

纯CSS自动补全:纯CSS代码会自动补全为完整HTML并应用样式

5

<h1>Hello World</h1>

页面显示一级标题

HTML片段补全:自动添加<html>,<head>,<body>结构

6

<style>p { color: blue; }</style><p>蓝色文字</p>

蓝色段落文字

混合片段:同时包含style和普通标签,无需DOCTYPE也能正确渲染

7

空内容(清空编辑器后运行)

自动加载默认示例卡片

空输入处理:应显示带渐变背景的默认欢迎页

8

<!DOCTYPE html>

  <html>

    <head>

        <meta charset="UTF-8">

        <title>完整页</title>

     </head>

     <body>

        <h1>完整页面</h1>

     </body>

</html>

显示“完整页面”标题

完整文档保持原样:不做任何修改直接渲染

9

<img src="https://picsum.photos/200" alt="示例图片">

显示一张随机图片

外部资源加载:验证图片能否正常请求和显示

10

setTimeout(() => { document.body.innerHTML += '<p>延迟出现</p>'; }, 1000);

1秒后页面出现“延迟出现”段落

异步JS:验证定时器能否在沙箱中正常工作

③ 较复杂用例

a.测试多console.log()

let age = 12;           // 把数字12放进"age"盒子
let name = "小明";      // 把文字放进"name"盒子

console.log(name,"我今年", age, "岁");   
age = age + 1;                  // age变成13
console.log("明年我就", age, "岁了");

let hero = "哈利";
let score = 100;
console.log(`勇士${hero}获得了${score}分!`);

b. 测试 HTML 结构
<h1>你好,世界!</h1>
<p>这是一个纯 HTML 测试。</p>


c. 测试 CSS 样式
<style>
  body { background: #ffeaa7; font-family: sans-serif; }
  .box { 
    width: 200px; height: 200px; background: #fd79a8; 
    margin: 50px auto; border-radius: 20px;
    display: flex; align-items: center; justify-content: center;
    color: white; font-size: 24px;
  }
</style>
<div class="box">CSS 样式正常</div>


d. 测试 JavaScript 交互
<button οnclick="document.getElementById('msg').textContent = 'JS 运行成功!'">
  点击测试 JavaScript
</button>
<p id="msg"></p>


e. 综合计数器(HTML + CSS + JS)
<style>
  body { font-family: Arial; text-align: center; padding-top: 80px; }
  button { padding: 10px 20px; font-size: 20px; margin: 10px; }
  #count { font-size: 48px; color: #2d3436; }
</style>

<h1>简单计数器</h1>
<p id="count">0</p>
<button οnclick="change(-1)">➖ 减少</button>
<button οnclick="change(1)">➕ 增加</button>

<script>
  let num = 0;
  function change(delta) {
    num += delta;
    document.getElementById('count').textContent = num;
  }
</script>
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习&认知实践爱好者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值