【html word富文本编辑器 gemini3pro】

还有很多的bugs,能简单的用

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>网页版富文本编辑器 (类Word)</title>
    <!-- 引入 FontAwesome 图标库 (需要联网,为了界面美观) -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        :root {
            --primary-color: #2b579a; /* Word 蓝 */
            --hover-bg: #f0f0f0;
            --border-color: #ccc;
            --toolbar-bg: #f3f2f1;
        }

        body {
            margin: 0;
            padding: 0;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background-color: #eef2f5;
            display: flex;
            flex-direction: column;
            height: 100vh;
        }

        /* --- 工具栏区域 --- */
        .toolbar-container {
            background-color: var(--toolbar-bg);
            border-bottom: 1px solid var(--border-color);
            padding: 8px 15px;
            display: flex;
            flex-wrap: wrap;
            gap: 5px;
            align-items: center;
            position: sticky;
            top: 0;
            z-index: 1000;
            box-shadow: 0 2px 5px rgba(0,0,0,0.05);
        }

        .tool-group {
            display: flex;
            align-items: center;
            border-right: 1px solid #ddd;
            padding-right: 10px;
            margin-right: 5px;
            gap: 2px;
        }
        .tool-group:last-child {
            border-right: none;
        }

        button {
            background: transparent;
            border: 1px solid transparent;
            cursor: pointer;
            padding: 6px 8px;
            border-radius: 3px;
            font-size: 14px;
            color: #333;
            transition: all 0.2s;
        }

        button:hover {
            background-color: #e1dfdd;
        }

        button.active {
            background-color: #cdaec7; /* 选中状态稍有不同 */
            background-color: #d1e0f3;
            color: var(--primary-color);
            border-color: #b3d7ff;
        }

        select {
            padding: 5px;
            border: 1px solid transparent;
            border-radius: 3px;
            background: transparent;
            cursor: pointer;
        }
        select:hover {
            background-color: #e1dfdd;
        }

        /* 颜色选择器特殊处理 */
        .color-wrapper {
            position: relative;
            display: flex;
            align-items: center;
        }
        input[type="color"] {
            width: 20px;
            height: 20px;
            border: none;
            padding: 0;
            background: transparent;
            cursor: pointer;
            margin-left: -25px; 
            opacity: 0; /* 隐藏原生控件,覆盖在图标上 */
            z-index: 2;
        }
        .color-icon {
            pointer-events: none;
        }

        /* --- 编辑区域 (模拟 A4 纸) --- */
        .editor-workspace {
            flex: 1;
            overflow-y: auto;
            padding: 30px 0;
            display: flex;
            justify-content: center;
        }

        #editor {
            background-color: white;
            width: 210mm; /* A4 宽度 */
            min-height: 297mm; /* A4 高度 */
            padding: 25mm; /* 页边距 */
            box-shadow: 0 4px 15px rgba(0,0,0,0.1);
            outline: none;
            box-sizing: border-box;
            font-size: 16px;
            line-height: 1.6;
            color: #000;
        }

        /* 打印时的样式 */
        @media print {
            body {
                background: white;
                height: auto;
                display: block;
            }
            .toolbar-container {
                display: none;
            }
            .editor-workspace {
                padding: 0;
                display: block;
            }
            #editor {
                width: 100%;
                min-height: auto;
                box-shadow: none;
                padding: 0;
                margin: 0;
            }
        }

        /* 图片样式控制 */
        #editor img {
            max-width: 100%;
            height: auto;
            cursor: pointer;
        }
        #editor blockquote {
            border-left: 4px solid var(--primary-color);
            margin: 0;
            padding-left: 15px;
            color: #666;
            background: #f9f9f9;
            padding: 10px;
        }
        #editor hr {
            border: 0;
            border-top: 1px solid #ccc;
            margin: 20px 0;
        }
    </style>
</head>
<body>

    <!-- 工具栏 -->
    <div class="toolbar-container">
        <!-- 常用操作 -->
        <div class="tool-group">
            <button onclick="execCmd('undo')" title="撤销"><i class="fa-solid fa-rotate-left"></i></button>
            <button onclick="execCmd('redo')" title="重做"><i class="fa-solid fa-rotate-right"></i></button>
            <button onclick="execCmd('removeFormat')" title="清除格式"><i class="fa-solid fa-eraser"></i></button>
        </div>

        <!-- 字体设置 -->
        <div class="tool-group">
            <select onchange="execCmd('formatBlock', this.value)" title="标题格式">
                <option value="P">正文</option>
                <option value="H1">标题 1</option>
                <option value="H2">标题 2</option>
                <option value="H3">标题 3</option>
                <option value="BLOCKQUOTE">引用</option>
            </select>
            <select onchange="execCmd('fontName', this.value)" title="字体">
                <option value="Arial">Arial</option>
                <option value="'Microsoft YaHei', sans-serif">微软雅黑</option>
                <option value="'SimSun', serif">宋体</option>
                <option value="'Courier New', monospace">等宽字体</option>
            </select>
            <select onchange="execCmd('fontSize', this.value)" title="字号">
                <option value="3">正常</option>
                <option value="1">小号</option>
                <option value="4">中大</option>
                <option value="5">大号</option>
                <option value="6">特大</option>
                <option value="7">超大</option>
            </select>
        </div>

        <!-- 文本样式 -->
        <div class="tool-group">
            <button onclick="execCmd('bold')" title="加粗"><i class="fa-solid fa-bold"></i></button>
            <button onclick="execCmd('italic')" title="斜体"><i class="fa-solid fa-italic"></i></button>
            <button onclick="execCmd('underline')" title="下划线"><i class="fa-solid fa-underline"></i></button>
            <button onclick="execCmd('strikeThrough')" title="删除线"><i class="fa-solid fa-strikethrough"></i></button>
        </div>

        <!-- 颜色 -->
        <div class="tool-group">
            <div class="color-wrapper" title="字体颜色">
                <button class="color-icon"><i class="fa-solid fa-font" style="color:red; border-bottom: 3px solid red;"></i></button>
                <input type="color" onchange="execCmd('foreColor', this.value)">
            </div>
            <div class="color-wrapper" title="背景高亮">
                <button class="color-icon"><i class="fa-solid fa-highlighter" style="color:orange; border-bottom: 3px solid orange;"></i></button>
                <input type="color" onchange="execCmd('hiliteColor', this.value)" value="#ffff00">
            </div>
        </div>

        <!-- 对齐方式 -->
        <div class="tool-group">
            <button onclick="execCmd('justifyLeft')" title="左对齐"><i class="fa-solid fa-align-left"></i></button>
            <button onclick="execCmd('justifyCenter')" title="居中"><i class="fa-solid fa-align-center"></i></button>
            <button onclick="execCmd('justifyRight')" title="右对齐"><i class="fa-solid fa-align-right"></i></button>
            <button onclick="execCmd('justifyFull')" title="两端对齐"><i class="fa-solid fa-align-justify"></i></button>
        </div>

        <!-- 列表与缩进 -->
        <div class="tool-group">
            <button onclick="execCmd('insertUnorderedList')" title="无序列表"><i class="fa-solid fa-list-ul"></i></button>
            <button onclick="execCmd('insertOrderedList')" title="有序列表"><i class="fa-solid fa-list-ol"></i></button>
            <button onclick="execCmd('indent')" title="增加缩进"><i class="fa-solid fa-indent"></i></button>
            <button onclick="execCmd('outdent')" title="减少缩进"><i class="fa-solid fa-outdent"></i></button>
        </div>

        <!-- 插入元素 -->
        <div class="tool-group">
            <button onclick="insertLink()" title="插入链接"><i class="fa-solid fa-link"></i></button>
            <button onclick="triggerImageUpload()" title="插入图片"><i class="fa-regular fa-image"></i></button>
            <button onclick="execCmd('insertHorizontalRule')" title="插入分割线"><i class="fa-solid fa-minus"></i></button>
            <!-- 隐藏的文件上传 input -->
            <input type="file" id="imageInput" accept="image/*" style="display: none;" onchange="handleImageUpload(this)">
        </div>

        <!-- 文件操作 -->
        <div class="tool-group" style="margin-left: auto; border: none;">
            <button onclick="exportHTML()" title="导出为HTML"><i class="fa-solid fa-download"></i> 导出</button>
            <button onclick="window.print()" title="打印"><i class="fa-solid fa-print"></i></button>
        </div>
    </div>

    <!-- 编辑区域 -->
    <div class="editor-workspace" onclick="focusEditor()">
        <div id="editor" contenteditable="true">
            <h1>欢迎使用简易网页版文档编辑器</h1>
            <p>这是一个<b>类似 Word</b> 的富文本编辑区域。</p>
            <p>你可以直接在这里输入文字,或者使用上方的工具栏进行格式化。</p>
            <ul>
                <li>支持加粗、斜体、下划线</li>
                <li>支持插入图片(自动转为 Base64 编码,随文件保存)</li>
                <li>支持导出为 HTML 文件</li>
            </ul>
            <p>请试着编辑这段文字...</p>
        </div>
    </div>

    <script>
        // 核心命令执行函数
        function execCmd(command, value = null) {
            // 重新聚焦编辑器,确保命令执行在正确位置
            document.getElementById('editor').focus();
            // 执行浏览器内置的编辑命令
            document.execCommand(command, false, value);
            updateButtonStates();
        }

        // 插入链接
        function insertLink() {
            const url = prompt("请输入链接地址 (如 https://www.example.com):", "http://");
            if (url) {
                execCmd('createLink', url);
            }
        }

        // 触发图片上传
        function triggerImageUpload() {
            document.getElementById('imageInput').click();
        }

        // 处理图片上传 (转为 Base64 以便在一个文件中保存)
        function handleImageUpload(input) {
            if (input.files && input.files[0]) {
                const reader = new FileReader();
                reader.onload = function (e) {
                    // 插入图片到光标位置
                    execCmd('insertImage', e.target.result);
                };
                reader.readAsDataURL(input.files[0]);
            }
            // 清空 input 防止重复上传同一张图不触发 onchange
            input.value = '';
        }

        // 导出为 HTML 文件
        function exportHTML() {
            const content = document.getElementById('editor').innerHTML;
            const html = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>导出的文档</title>
<style>
    body { font-family: sans-serif; max-width: 800px; margin: 20px auto; padding: 20px; line-height: 1.6; }
    img { max-width: 100%; height: auto; }
    blockquote { border-left: 4px solid #ccc; margin: 0; padding-left: 15px; color: #666; }
</style>
</head>
<body>
${content}
</body>
</html>`;
            
            const blob = new Blob([html], { type: 'text/html' });
            const a = document.createElement('a');
            a.href = URL.createObjectURL(blob);
            a.download = 'document.html';
            a.click();
        }

        // 点击灰色背景聚焦到编辑器
        function focusEditor() {
            // 只有点击的不是编辑器本身时才聚焦
            if(event.target.classList.contains('editor-workspace')) {
               document.getElementById('editor').focus(); 
            }
        }

        // 更新按钮激活状态 (简单的 UX 优化)
        const editor = document.getElementById('editor');
        const buttons = document.querySelectorAll('button[onclick^="execCmd"]');

        function updateButtonStates() {
            // 这是一个简化的状态检测,document.queryCommandState 可以检测当前光标位置是否应用了某种样式
            buttons.forEach(btn => {
                const cmd = btn.getAttribute('onclick').match(/'([^']+)'/)[1];
                try {
                    if (document.queryCommandState(cmd)) {
                        btn.classList.add('active');
                    } else {
                        btn.classList.remove('active');
                    }
                } catch (e) {
                    // 某些命令不支持 queryCommandState,忽略
                }
            });
        }

        // 监听键盘和鼠标事件以更新工具栏状态
        editor.addEventListener('keyup', updateButtonStates);
        editor.addEventListener('mouseup', updateButtonStates);
        editor.addEventListener('click', updateButtonStates);
        
        // 初始化
        document.getElementById('editor').focus();
    </script>
</body>
</html>
相关推荐
囨誌5 小时前
vben admin表格常用配置
前端·javascript·html
止水编程 water_proof6 小时前
HTML---CSS(基础)
前端·css·html
Hi~晴天大圣6 小时前
html页面交互及JS(JavaScript)使用方法
javascript·html·交互
鱼锦0.018 小时前
在vue2中主页面怎么给子页面传递数据
前端·javascript·html
serve the people1 天前
HTML Document Loaders in LangChain
chrome·langchain·html
just小千1 天前
HTML进阶——常用标签及其属性
前端·html
惜.己1 天前
html笔记(一)
前端·笔记·html
曹牧1 天前
HTML实体名称
前端·html
guangzan1 天前
在 React 中重拾原生 HTML 属性
html