【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>
相关推荐
爱上好庆祝4 小时前
学习js的第五天
前端·css·学习·html·css3·js
前端老石人5 小时前
前端开发中的 URL 完全指南
开发语言·前端·javascript·css·html
jingqingdai37 小时前
别用正则格式化 HTML!我用 DOM 遍历实现零风险本地格式化,老项目重构效率直接拉满
前端·重构·html
a1117769 小时前
“像风之翼“无人机巡检平台仪表盘
前端·javascript·开源·html·无人机
a1117769 小时前
QQ 宠物(怀旧 开源)前端electron项目
前端·开源·html
ZC跨境爬虫9 小时前
跟着 MDN 学 HTML day_8:(高级文本语义标签+适配核心功底)
前端·css·笔记·ui·html
Dxy12393102169 小时前
HTML中的伪类详解:从基础到高级应用的全面指南
前端·html
Dxy12393102169 小时前
HTML中如何设置元素样式:从基础到进阶的完整指南
前端·html
寒山李白19 小时前
解决 python-docx 生成的 Word 文档打开时弹出“无法读取内容“警告
python·word·wps·文档·docx·qoder
DFT计算杂谈1 天前
VASP官方教程 TRIQS DFT+DMFT计算教程
运维·css·自动化·html·css3