<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>高级富文本编辑器</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.editor-container {
width: 90%;
max-width: 1000px;
background-color: white;
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
overflow: hidden;
}
.editor-header {
background: linear-gradient(to right, #4b6cb7, #182848);
color: white;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.editor-title {
font-size: 1.8rem;
font-weight: 600;
}
.theme-selector {
display: flex;
gap: 10px;
align-items: center;
}
.theme-btn {
width: 24px;
height: 24px;
border-radius: 50%;
border: 2px solid white;
cursor: pointer;
transition: transform 0.2s;
}
.theme-btn:hover {
transform: scale(1.1);
}
.theme-btn.active {
transform: scale(1.2);
box-shadow: 0 0 0 2px #333;
}
.toolbar {
display: flex;
flex-wrap: wrap;
gap: 8px;
padding: 15px;
background-color: #f8f9fa;
border-bottom: 1px solid #e0e0e0;
}
.toolbar-group {
display: flex;
gap: 5px;
padding: 0 10px;
border-right: 1px solid #e0e0e0;
}
.toolbar-group:last-child {
border-right: none;
}
.toolbar-btn {
background-color: #f0f0f0;
border: 1px solid #ddd;
padding: 8px 12px;
cursor: pointer;
font-size: 14px;
border-radius: 4px;
display: flex;
align-items: center;
gap: 5px;
transition: all 0.2s;
}
.toolbar-btn:hover {
background-color: #e0e0e0;
transform: translateY(-2px);
}
.toolbar-btn.active {
background-color: #4b6cb7;
color: white;
}
.font-selector {
display: flex;
align-items: center;
gap: 5px;
}
.font-selector select,
.font-selector input {
padding: 6px 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
.editor {
min-height: 400px;
padding: 20px;
border: none;
font-family: Arial, sans-serif;
font-size: 16px;
line-height: 1.6;
outline: none;
overflow-y: auto;
max-height: 500px;
}
.editor:focus {
box-shadow: inset 0 0 0 2px #4b6cb7;
border-radius: 4px;
}
.download-options {
padding: 20px;
background-color: #f8f9fa;
display: flex;
justify-content: flex-end;
gap: 15px;
border-top: 1px solid #e0e0e0;
}
.download-btn {
padding: 12px 24px;
background: linear-gradient(to right, #4b6cb7, #182848);
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
font-weight: 500;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.3s;
}
.download-btn:hover {
transform: translateY(-3px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}
.status-bar {
padding: 10px 20px;
background-color: #f8f9fa;
border-top: 1px solid #e0e0e0;
font-size: 14px;
color: #666;
display: flex;
justify-content: space-between;
}
.theme-light {
--bg-color: #ffffff;
--text-color: #333333;
--toolbar-bg: #f8f9fa;
--border-color: #e0e0e0;
}
.theme-dark {
--bg-color: #2c3e50;
--text-color: #ecf0f1;
--toolbar-bg: #34495e;
--border-color: #4a5f7a;
}
.theme-sepia {
--bg-color: #fdf6e3;
--text-color: #586e75;
--toolbar-bg: #eee8d5;
--border-color: #d6d0c3;
}
.theme-mono {
--bg-color: #000000;
--text-color: #00ff00;
--toolbar-bg: #111111;
--border-color: #333333;
}
.theme-dark .editor-container,
.theme-sepia .editor-container,
.theme-mono .editor-container {
background-color: var(--bg-color);
color: var(--text-color);
}
.theme-dark .toolbar,
.theme-sepia .toolbar,
.theme-mono .toolbar {
background-color: var(--toolbar-bg);
border-bottom: 1px solid var(--border-color);
}
.theme-dark .download-options,
.theme-sepia .download-options,
.theme-mono .download-options {
background-color: var(--toolbar-bg);
border-top: 1px solid var(--border-color);
}
.theme-dark .status-bar,
.theme-sepia .status-bar,
.theme-mono .status-bar {
background-color: var(--toolbar-bg);
border-top: 1px solid var(--border-color);
}
.theme-dark .toolbar-btn,
.theme-sepia .toolbar-btn,
.theme-mono .toolbar-btn {
background-color: var(--toolbar-bg);
border: 1px solid var(--border-color);
color: var(--text-color);
}
.theme-dark .toolbar-btn:hover,
.theme-sepia .toolbar-btn:hover,
.theme-mono .toolbar-btn:hover {
background-color: var(--border-color);
}
.theme-dark .editor,
.theme-sepia .editor,
.theme-mono .editor {
color: var(--text-color);
}
.theme-dark .editor:focus,
.theme-sepia .editor:focus,
.theme-mono .editor:focus {
box-shadow: inset 0 0 0 2px #4b6cb7;
}
.theme-dark .download-btn,
.theme-sepia .download-btn,
.theme-mono .download-btn {
background: linear-gradient(to right, #4b6cb7, #182848);
}
.color-picker {
display: flex;
align-items: center;
gap: 5px;
}
.color-input {
width: 30px;
height: 30px;
border: none;
border-radius: 4px;
cursor: pointer;
}
@media (max-width: 768px) {
.toolbar {
flex-direction: column;
}
.toolbar-group {
border-right: none;
border-bottom: 1px solid #e0e0e0;
padding-bottom: 10px;
}
.editor-header {
flex-direction: column;
gap: 15px;
text-align: center;
}
.theme-selector {
justify-content: center;
}
}
</style>
</head>
<body>
<div class="editor-container theme-light">
<div class="editor-header">
<h1 class="editor-title"><i class="fas fa-edit"></i> 高级富文本编辑器</h1>
<div class="theme-selector">
<div class="theme-btn active" style="background-color: #ffffff;" data-theme="light" title="明亮主题"></div>
<div class="theme-btn" style="background-color: #2c3e50;" data-theme="dark" title="暗黑主题"></div>
<div class="theme-btn" style="background-color: #fdf6e3;" data-theme="sepia" title="护眼主题"></div>
<div class="theme-btn" style="background-color: #000000;" data-theme="mono" title="代码主题"></div>
</div>
</div>
<div class="toolbar">
<div class="toolbar-group">
<button class="toolbar-btn" onclick="execCommand('undo')" title="撤销">
<i class="fas fa-undo"></i>
</button>
<button class="toolbar-btn" onclick="execCommand('redo')" title="重做">
<i class="fas fa-redo"></i>
</button>
</div>
<div class="toolbar-group">
<button class="toolbar-btn" onclick="execCommand('bold')" title="粗体">
<i class="fas fa-bold"></i>
</button>
<button class="toolbar-btn" onclick="execCommand('italic')" title="斜体">
<i class="fas fa-italic"></i>
</button>
<button class="toolbar-btn" onclick="execCommand('underline')" title="下划线">
<i class="fas fa-underline"></i>
</button>
</div>
<div class="toolbar-group">
<div class="font-selector">
<select class="toolbar-btn" onchange="execCommand('fontName', this.value)" title="字体">
<option value="Arial">Arial</option>
<option value="Helvetica">Helvetica</option>
<option value="Times New Roman">Times New Roman</option>
<option value="Courier New">Courier New</option>
<option value="Georgia">Georgia</option>
<option value="Verdana">Verdana</option>
<option value="Comic Sans MS">Comic Sans MS</option>
<option value="Impact">Impact</option>
</select>
</div>
<div class="font-selector">
<select class="toolbar-btn" onchange="execCommand('fontSize', this.value)" title="字体大小">
<option value="1">8px</option>
<option value="2">10px</option>
<option value="3">12px</option>
<option value="4" selected>14px</option>
<option value="5">16px</option>
<option value="6">18px</option>
<option value="7">20px</option>
</select>
</div>
<div class="color-picker">
<label for="text-color" title="文字颜色"><i class="fas fa-palette"></i></label>
<input type="color" id="text-color" class="color-input" value="#000000" onchange="execCommand('foreColor', this.value)">
</div>
<div class="color-picker">
<label for="bg-color" title="背景色"><i class="fas fa-fill-drip"></i></label>
<input type="color" id="bg-color" class="color-input" value="#ffffff" onchange="execCommand('backColor', this.value)">
</div>
</div>
<div class="toolbar-group">
<button class="toolbar-btn" onclick="execCommand('insertOrderedList')" title="编号列表">
<i class="fas fa-list-ol"></i>
</button>
<button class="toolbar-btn" onclick="execCommand('insertUnorderedList')" title="项目符号">
<i class="fas fa-list-ul"></i>
</button>
</div>
<div class="toolbar-group">
<button class="toolbar-btn" onclick="execCommand('justifyLeft')" title="左对齐">
<i class="fas fa-align-left"></i>
</button>
<button class="toolbar-btn" onclick="execCommand('justifyCenter')" title="居中">
<i class="fas fa-align-center"></i>
</button>
<button class="toolbar-btn" onclick="execCommand('justifyRight')" title="右对齐">
<i class="fas fa-align-right"></i>
</button>
<button class="toolbar-btn" onclick="execCommand('justifyFull')" title="两端对齐">
<i class="fas fa-align-justify"></i>
</button>
</div>
<div class="toolbar-group">
<button class="toolbar-btn" onclick="execCommand('createLink')" title="插入链接">
<i class="fas fa-link"></i>
</button>
<button class="toolbar-btn" onclick="execCommand('insertImage')" title="插入图片">
<i class="fas fa-image"></i>
</button>
<button class="toolbar-btn" onclick="execCommand('insertHorizontalRule')" title="插入分割线">
<i class="fas fa-grip-lines"></i>
</button>
</div>
</div>
<div class="editor" contenteditable="true">
<h2>欢迎使用高级富文本编辑器</h2>
<p>这是一个功能强大的富文本编辑器,支持以下功能:</p>
<ul>
<li>选中特定文字进行格式修改</li>
<li>多种主题切换(明亮、暗黑、护眼、代码)</li>
<li>丰富的字体和颜色选择</li>
<li>列表、对齐等格式化功能</li>
<li>下载文本或HTML格式文件</li>
</ul>
<p>您可以选中这段文字,然后使用工具栏对选中的文字进行格式化。</p>
<p>试试看吧!</p>
</div>
<div class="status-bar">
<div class="word-count">字数: <span id="count">0</span></div>
<div class="theme-info">当前主题: <span id="theme-name">明亮</span></div>
</div>
<div class="download-options">
<button class="download-btn" onclick="downloadText()">
<i class="fas fa-file-alt"></i> 下载文本
</button>
<button class="download-btn" onclick="downloadHTML()">
<i class="fas fa-code"></i> 下载HTML
</button>
</div>
</div>
<script>
// 主题切换功能
const themeButtons = document.querySelectorAll('.theme-btn');
const editorContainer = document.querySelector('.editor-container');
const themeName = document.getElementById('theme-name');
themeButtons.forEach(button => {
button.addEventListener('click', () => {
// 移除所有活动状态
themeButtons.forEach(btn => btn.classList.remove('active'));
// 添加当前选中状态
button.classList.add('active');
// 获取主题值
const theme = button.getAttribute('data-theme');
// 应用主题
editorContainer.className = 'editor-container theme-' + theme;
// 更新状态栏
const themeDisplayNames = {
'light': '明亮',
'dark': '暗黑',
'sepia': '护眼',
'mono': '代码'
};
themeName.textContent = themeDisplayNames[theme];
});
});
// 执行编辑命令
function execCommand(command, value = null) {
document.execCommand(command, false, value);
document.querySelector('.editor').focus();
}
// 下载纯文本文件
function downloadText() {
const content = document.querySelector('.editor').innerText;
const blob = new Blob([content], { type: 'text/plain' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'document.txt';
link.click();
}
// 下载HTML文件
function downloadHTML() {
const content = document.querySelector('.editor').innerHTML;
const blob = new Blob([`<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>文档</title>
<style>
body { font-family: Arial, sans-serif; }
</style>
</head>
<body>
${content}
</body>
</html>`], { type: 'text/html' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'document.html';
link.click();
}
// 实时更新字数
const editor = document.querySelector('.editor');
const wordCount = document.getElementById('count');
editor.addEventListener('input', updateWordCount);
function updateWordCount() {
const text = editor.innerText || editor.textContent;
wordCount.textContent = text.length;
}
// 初始化字数
updateWordCount();
// 防止某些命令导致编辑器失去焦点
document.querySelectorAll('.toolbar-btn').forEach(button => {
button.addEventListener('mousedown', function(e) {
e.preventDefault();
});
});
// 模拟插入图片功能(实际项目中需要实现文件上传)
document.querySelector('[title="插入图片"]').addEventListener('click', function() {
const url = prompt('请输入图片URL:', 'https://via.placeholder.com/300x200.png');
if (url) {
execCommand('insertImage', url);
}
});
// 模拟插入链接功能
document.querySelector('[title="插入链接"]').addEventListener('click', function() {
const url = prompt('请输入链接地址:', 'https://example.com');
if (url) {
execCommand('createLink', url);
}
});
</script>
</body>
</html>
index.html
index.html