DeepseekV3.2 实现构建简易版Wiki系统:从零开始的HTML实现

DeepseekV3.2 实现构建简易版Wiki系统:从零开始的HTML实现

我将为您创建一个功能完整的简易版Wiki系统,包含文章展示、编辑、搜索等核心功能,并按照要求包含三个表格、三个链接和代码示例。

设计思路

这个简易Wiki系统将包含以下核心功能:

  • 主页文章列表展示
  • 文章查看和编辑功能
  • 搜索功能
  • 本地存储(使用localStorage)

下面是完整的实现代码:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>简易Wiki系统</title>
    <style>
        :root {
            --primary-color: #3498db;
            --secondary-color: #2980b9;
            --accent-color: #e74c3c;
            --light-color: #ecf0f1;
            --dark-color: #2c3e50;
            --text-color: #333;
            --border-radius: 4px;
            --box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        }

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }

        body {
            background-color: #f5f7fa;
            color: var(--text-color);
            line-height: 1.6;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 0 20px;
        }

        header {
            background-color: var(--primary-color);
            color: white;
            padding: 1rem 0;
            box-shadow: var(--box-shadow);
            position: sticky;
            top: 0;
            z-index: 100;
        }

        .header-content {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .logo {
            font-size: 1.8rem;
            font-weight: bold;
        }

        nav ul {
            display: flex;
            list-style: none;
        }

        nav ul li {
            margin-left: 1.5rem;
        }

        nav ul li a {
            color: white;
            text-decoration: none;
            padding: 0.5rem 1rem;
            border-radius: var(--border-radius);
            transition: background-color 0.3s;
        }

        nav ul li a:hover {
            background-color: var(--secondary-color);
        }

        .search-container {
            margin: 2rem 0;
            display: flex;
            justify-content: center;
        }

        .search-box {
            width: 70%;
            padding: 0.8rem 1.2rem;
            border: 1px solid #ddd;
            border-radius: 30px;
            font-size: 1rem;
            box-shadow: var(--box-shadow);
            transition: box-shadow 0.3s;
        }

        .search-box:focus {
            outline: none;
            box-shadow: 0 2px 15px rgba(0, 0, 0, 0.15);
            border-color: var(--primary-color);
        }

        .main-content {
            display: grid;
            grid-template-columns: 1fr 3fr;
            gap: 2rem;
            margin: 2rem 0;
        }

        .sidebar {
            background-color: white;
            padding: 1.5rem;
            border-radius: var(--border-radius);
            box-shadow: var(--box-shadow);
            height: fit-content;
        }

        .sidebar h3 {
            margin-bottom: 1rem;
            color: var(--dark-color);
            border-bottom: 2px solid var(--primary-color);
            padding-bottom: 0.5rem;
        }

        .sidebar ul {
            list-style: none;
        }

        .sidebar ul li {
            margin-bottom: 0.7rem;
        }

        .sidebar ul li a {
            color: var(--text-color);
            text-decoration: none;
            display: block;
            padding: 0.5rem;
            border-radius: var(--border-radius);
            transition: background-color 0.3s;
        }

        .sidebar ul li a:hover {
            background-color: var(--light-color);
            color: var(--primary-color);
        }

        .content {
            background-color: white;
            padding: 2rem;
            border-radius: var(--border-radius);
            box-shadow: var(--box-shadow);
            min-height: 500px;
        }

        .article-header {
            margin-bottom: 1.5rem;
            padding-bottom: 1rem;
            border-bottom: 1px solid #eee;
        }

        .article-header h1 {
            color: var(--dark-color);
            margin-bottom: 0.5rem;
        }

        .article-meta {
            color: #777;
            font-size: 0.9rem;
        }

        .article-content {
            line-height: 1.8;
        }

        .article-content h2, .article-content h3 {
            margin: 1.5rem 0 1rem 0;
            color: var(--dark-color);
        }

        .article-content p {
            margin-bottom: 1rem;
        }

        .article-content ul, .article-content ol {
            margin-bottom: 1rem;
            padding-left: 2rem;
        }

        .article-content table {
            width: 100%;
            border-collapse: collapse;
            margin: 1.5rem 0;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.05);
        }

        .article-content table th, .article-content table td {
            padding: 0.8rem 1rem;
            text-align: left;
            border-bottom: 1px solid #eee;
        }

        .article-content table th {
            background-color: var(--light-color);
            font-weight: 600;
        }

        .article-content table tr:hover {
            background-color: #f9f9f9;
        }

        .article-content code {
            background-color: #f4f4f4;
            padding: 0.2rem 0.4rem;
            border-radius: 3px;
            font-family: 'Courier New', Courier, monospace;
        }

        .article-content pre {
            background-color: #f8f8f8;
            padding: 1rem;
            border-radius: var(--border-radius);
            overflow-x: auto;
            margin: 1.5rem 0;
        }

        .article-content blockquote {
            border-left: 4px solid var(--primary-color);
            padding-left: 1rem;
            margin: 1.5rem 0;
            color: #555;
            font-style: italic;
        }

        .article-actions {
            display: flex;
            justify-content: flex-end;
            margin-top: 2rem;
            padding-top: 1rem;
            border-top: 1px solid #eee;
        }

        .btn {
            padding: 0.6rem 1.2rem;
            border: none;
            border-radius: var(--border-radius);
            cursor: pointer;
            font-size: 0.9rem;
            transition: all 0.3s;
            text-decoration: none;
            display: inline-block;
        }

        .btn-primary {
            background-color: var(--primary-color);
            color: white;
        }

        .btn-primary:hover {
            background-color: var(--secondary-color);
        }

        .btn-secondary {
            background-color: var(--light-color);
            color: var(--text-color);
        }

        .btn-secondary:hover {
            background-color: #ddd;
        }

        .btn-danger {
            background-color: var(--accent-color);
            color: white;
        }

        .btn-danger:hover {
            background-color: #c0392b;
        }

        .edit-form textarea {
            width: 100%;
            min-height: 400px;
            padding: 1rem;
            border: 1px solid #ddd;
            border-radius: var(--border-radius);
            font-size: 1rem;
            line-height: 1.6;
            resize: vertical;
            margin-bottom: 1rem;
        }

        .edit-form input[type="text"] {
            width: 100%;
            padding: 0.8rem 1rem;
            border: 1px solid #ddd;
            border-radius: var(--border-radius);
            font-size: 1.2rem;
            margin-bottom: 1rem;
        }

        .articles-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
            gap: 1.5rem;
        }

        .article-card {
            background-color: white;
            border-radius: var(--border-radius);
            box-shadow: var(--box-shadow);
            overflow: hidden;
            transition: transform 0.3s, box-shadow 0.3s;
        }

        .article-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
        }

        .article-card-content {
            padding: 1.5rem;
        }

        .article-card h3 {
            margin-bottom: 0.5rem;
            color: var(--dark-color);
        }

        .article-card p {
            color: #666;
            font-size: 0.9rem;
            margin-bottom: 1rem;
        }

        .article-card .meta {
            color: #999;
            font-size: 0.8rem;
        }

        footer {
            background-color: var(--dark-color);
            color: white;
            text-align: center;
            padding: 2rem 0;
            margin-top: 3rem;
        }

        .alert {
            padding: 1rem;
            border-radius: var(--border-radius);
            margin-bottom: 1.5rem;
        }

        .alert-success {
            background-color: #d4edda;
            color: #155724;
            border: 1px solid #c3e6cb;
        }

        .alert-error {
            background-color: #f8d7da;
            color: #721c24;
            border: 1px solid #f5c6cb;
        }

        .hidden {
            display: none;
        }

        @media (max-width: 768px) {
            .main-content {
                grid-template-columns: 1fr;
            }
            
            .header-content {
                flex-direction: column;
                text-align: center;
            }
            
            nav ul {
                margin-top: 1rem;
                justify-content: center;
            }
            
            .search-box {
                width: 90%;
            }
        }
    </style>
</head>
<body>
    <header>
        <div class="container">
            <div class="header-content">
                <div class="logo">简易Wiki</div>
                <nav>
                    <ul>
                        <li><a href="#" id="home-link">首页</a></li>
                        <li><a href="#" id="create-link">创建文章</a></li>
                        <li><a href="#" id="about-link">关于</a></li>
                    </ul>
                </nav>
            </div>
        </div>
    </header>

    <div class="container">
        <div class="search-container">
            <input type="text" class="search-box" id="search-input" placeholder="搜索Wiki文章...">
        </div>

        <div class="main-content">
            <aside class="sidebar">
                <h3>文章分类</h3>
                <ul id="category-list">
                    <!-- 动态生成分类 -->
                </ul>
                
                <h3>热门文章</h3>
                <ul id="popular-articles">
                    <!-- 动态生成热门文章 -->
                </ul>
            </aside>

            <main class="content" id="content-area">
                <!-- 内容区域将动态加载 -->
            </main>
        </div>
    </div>

    <footer>
        <div class="container">
            <p>&copy; 2023 简易Wiki系统 | 基于HTML/CSS/JavaScript构建</p>
        </div>
    </footer>

    <script>
        // 文章数据模型
        const wikiArticles = {
            "home": {
                title: "简易Wiki系统使用指南",
                content: `
# 简易Wiki系统使用指南

欢迎使用简易Wiki系统!这是一个基于HTML/CSS/JavaScript构建的简易Wiki系统,无需后端支持,所有数据都存储在浏览器的localStorage中。

## 系统功能

1. **文章浏览** - 查看所有已创建的Wiki文章
2. **文章编辑** - 创建新文章或编辑现有文章
3. **搜索功能** - 通过关键词搜索文章内容
4. **分类管理** - 自动根据文章标签进行分类

## 使用方法

1. 点击"创建文章"开始编写新内容
2. 使用Markdown语法格式化您的文章
3. 保存后即可在首页看到您的文章
4. 使用搜索框快速查找特定内容

## 技术特点

- 纯前端实现,无需服务器
- 响应式设计,适配各种设备
- 使用localStorage进行数据持久化
- 支持Markdown语法

希望您喜欢这个简易Wiki系统!如有任何建议,欢迎反馈。
                `,
                category: "系统",
                tags: ["wiki", "指南", "使用"],
                created: "2023-10-01",
                updated: "2023-10-15",
                views: 125
            },
            "html-tutorial": {
                title: "HTML基础教程",
                content: `
# HTML基础教程

HTML(超文本标记语言)是构建网页的基础。本教程将介绍HTML的基本概念和常用标签。

## HTML文档结构

一个基本的HTML文档包含以下结构:

\`\`\`html
<!DOCTYPE html>
<html>
<head>
    <title>页面标题</title>
</head>
<body>
    <h1>这是一个标题</h1>
    <p>这是一个段落。</p>
</body>
</html>
\`\`\`

## 常用HTML标签

### 文本标签

- \`<h1> - <h6>\`:标题标签,从最重要到最不重要
- \`<p>\`:段落标签
- \`<strong>\`:强调文本(粗体)
- \`<em>\`:强调文本(斜体)
- \`<br>\`:换行标签

### 链接和图像

- \`<a href="url">链接文本</a>\`:创建超链接
- \`<img src="image.jpg" alt="描述">\`:插入图像

### 列表

- \`<ul>\`:无序列表
- \`<ol>\`:有序列表
- \`<li>\`:列表项

## HTML表格

HTML表格用于展示结构化数据。下面是一个简单的表格示例:

| 标签 | 描述 | 示例 |
|------|------|------|
| \`<table>\` | 定义表格 | \`<table></table>\` |
| \`<tr>\` | 定义表格行 | \`<tr></tr>\` |
| \`<th>\` | 定义表头单元格 | \`<th>姓名</th>\` |
| \`<td>\` | 定义标准单元格 | \`<td>张三</td>\` |

下面是一个更复杂的表格示例,展示编程语言比较:

<table>
<thead>
<tr>
<th>编程语言</th>
<th>发布年份</th>
<th>主要用途</th>
<th>学习难度</th>
</tr>
</thead>
<tbody>
<tr>
<td>JavaScript</td>
<td>1995</td>
<td>Web开发</td>
<td>中等</td>
</tr>
<tr>
<td>Python</td>
<td>1991</td>
<td>数据科学、AI</td>
<td>简单</td>
</tr>
<tr>
<td>Java</td>
<td>1995</td>
<td>企业应用</td>
<td>中等</td>
</tr>
<tr>
<td>C++</td>
<td>1985</td>
<td>系统编程、游戏</td>
<td>困难</td>
</tr>
</tbody>
</table>

## HTML表单

HTML表单用于收集用户输入。下面是一个简单的登录表单示例:

\`\`\`html
<form action="/login" method="post">
    <div>
        <label for="username">用户名:</label>
        <input type="text" id="username" name="username" required>
    </div>
    <div>
        <label for="password">密码:</label>
        <input type="password" id="password" name="password" required>
    </div>
    <div>
        <input type="submit" value="登录">
    </div>
</form>
\`\`\`

## 语义化HTML

语义化HTML使用有意义的标签来描述内容,这有助于搜索引擎优化和可访问性。

- \`<header>\`:页面或区域的页眉
- \`<nav>\`:导航链接
- \`<main>\`:页面主要内容
- \`<article>\`:独立的内容块
- \`<section>\`:文档中的节
- \`<aside>\`:侧边栏内容
- \`<footer>\`:页面或区域的页脚

## 进一步学习

要了解更多HTML知识,请参考以下资源:

1. [MDN Web文档 - HTML](https://developer.mozilla.org/zh-CN/docs/Web/HTML)
2. [W3Schools HTML教程](https://www.w3schools.com/html/)
3. [HTML标准规范](https://html.spec.whatwg.org/)

希望本教程对您学习HTML有所帮助!
                `,
                category: "前端开发",
                tags: ["html", "教程", "前端"],
                created: "2023-09-15",
                updated: "2023-10-10",
                views: 89
            },
            "css-guide": {
                title: "CSS样式指南",
                content: `
# CSS样式指南

CSS(层叠样式表)用于描述HTML元素在屏幕上的呈现方式。本指南将介绍CSS的核心概念和常用技巧。

## CSS基础语法

CSS规则由选择器和声明块组成:

\`\`\`css
selector {
    property: value;
    property: value;
}
\`\`\`

## CSS选择器

### 基本选择器

- 元素选择器:\`p { color: blue; }\`
- 类选择器:\`.className { font-size: 16px; }\`
- ID选择器:\`#idName { margin: 0; }\`
- 通用选择器:\`* { box-sizing: border-box; }\`

### 组合选择器

- 后代选择器:\`div p { line-height: 1.5; }\`
- 子元素选择器:\`ul > li { list-style: none; }\`
- 相邻兄弟选择器:\`h1 + p { margin-top: 0; }\`
- 通用兄弟选择器:\`h1 ~ p { color: #666; }\`

### 属性选择器

- \`[attribute]\`:选择带有指定属性的元素
- \`[attribute=value]\`:选择属性等于指定值的元素
- \`[attribute~=value]\`:选择属性包含指定词的元素
- \`[attribute|=value]\`:选择属性以指定值开头的元素

## CSS盒模型

每个HTML元素都可以看作一个盒子,包含内容、内边距、边框和外边距。

\`\`\`css
.box {
    width: 300px;
    height: 200px;
    padding: 20px;
    border: 2px solid #333;
    margin: 10px;
}
\`\`\`

## CSS布局

### Flexbox布局

Flexbox是一种一维布局模型,非常适合组件和小规模布局。

\`\`\`css
.container {
    display: flex;
    justify-content: center; /* 水平对齐 */
    align-items: center;     /* 垂直对齐 */
    flex-wrap: wrap;         /* 换行 */
}
\`\`\`

### Grid布局

CSS Grid是一个二维布局系统,非常适合整个页面的布局。

\`\`\`css
.container {
    display: grid;
    grid-template-columns: 1fr 2fr 1fr;
    grid-gap: 20px;
}
\`\`\`

## CSS响应式设计

响应式设计使网站能够适应不同屏幕尺寸。

### 媒体查询

\`\`\`css
/* 移动设备 */
@media (max-width: 768px) {
    .container {
        flex-direction: column;
    }
}

/* 平板设备 */
@media (min-width: 769px) and (max-width: 1024px) {
    .sidebar {
        width: 30%;
    }
}

/* 桌面设备 */
@media (min-width: 1025px) {
    .main-content {
        max-width: 1200px;
        margin: 0 auto;
    }
}
\`\`\`

## CSS变量

CSS自定义属性(变量)允许您在样式表中存储值并在整个文档中重复使用。

\`\`\`css
:root {
    --primary-color: #3498db;
    --secondary-color: #2980b9;
    --font-size: 16px;
}

.element {
    color: var(--primary-color);
    font-size: var(--font-size);
}
\`\`\`

## CSS动画

CSS动画可以为元素添加动态效果。

### 过渡(Transition)

\`\`\`css
.button {
    background-color: blue;
    transition: background-color 0.3s ease;
}

.button:hover {
    background-color: darkblue;
}
\`\`\`

### 关键帧动画(Animation)

\`\`\`css
@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

.element {
    animation: fadeIn 1s ease-in-out;
}
\`\`\`

## CSS框架比较

下面是一个流行的CSS框架比较表格:

<table>
<thead>
<tr>
<th>框架名称</th>
<th>特点</th>
<th>学习曲线</th>
<th>自定义能力</th>
<th>适用场景</th>
</tr>
</thead>
<tbody>
<tr>
<td>Bootstrap</td>
<td>组件丰富,文档完善</td>
<td>简单</td>
<td>中等</td>
<td>快速开发,企业网站</td>
</tr>
<tr>
<td>Tailwind CSS</td>
<td>实用工具优先,高度可定制</td>
<td>中等</td>
<td>高</td>
<td>定制化设计,组件库</td>
</tr>
<tr>
<td>Bulma</td>
<td>纯CSS框架,无JavaScript</td>
<td>简单</td>
<td>中等</td>
<td>轻量级项目,学习CSS</td>
</tr>
<tr>
<td>Foundation</td>
<td>企业级,响应式强</td>
<td>中等</td>
<td>高</td>
<td>复杂应用,企业网站</td>
</tr>
</tbody>
</table>

## CSS最佳实践

1. **使用语义化类名**:使用有意义的类名,如\`.card\`而不是\`.box1\`
2. **避免过度嵌套**:减少选择器嵌套深度,提高性能
3. **使用CSS变量**:便于维护和主题切换
4. **移动优先**:先为移动设备编写样式,然后使用媒体查询为更大屏幕添加样式
5. **性能优化**:减少重绘和回流,使用transform和opacity实现动画

## 浏览器兼容性考虑

不同浏览器对CSS特性的支持可能不同。使用以下方法处理兼容性问题:

- 使用autoprefixer自动添加浏览器前缀
- 使用特性查询(@supports)检测浏览器支持
- 提供回退方案

## 进一步学习

要深入了解CSS,请参考以下资源:

1. [MDN Web文档 - CSS](https://developer.mozilla.org/zh-CN/docs/Web/CSS)
2. [CSS-Tricks](https://css-tricks.com/) - CSS技巧和教程
3. [W3Schools CSS教程](https://www.w3schools.com/css/)

通过不断练习和尝试,您将掌握CSS的强大功能,创建出美观且功能强大的网页。
                `,
                category: "前端开发",
                tags: ["css", "样式", "前端"],
                created: "2023-09-20",
                updated: "2023-10-12",
                views: 76
            },
            "javascript-basics": {
                title: "JavaScript基础知识",
                content: `
# JavaScript基础知识

JavaScript是一种轻量级的解释型编程语言,主要用于Web开发。本教程将介绍JavaScript的核心概念和语法。

## JavaScript简介

JavaScript最初由Netscape的Brendan Eich在1995年创建,现在已成为Web开发的三大核心技术之一(与HTML和CSS并列)。

### JavaScript能做什么

- 操作HTML元素和CSS样式
- 响应用户交互事件
- 发送和接收服务器数据(AJAX)
- 创建动画和视觉效果
- 开发复杂的Web应用程序

## 基本语法

### 变量声明

\`\`\`javascript
// ES5方式
var name = "张三";

// ES6方式
let age = 25;
const PI = 3.14159;
\`\`\`

### 数据类型

JavaScript有7种基本数据类型:

1. **Number** - 数字类型
2. **String** - 字符串类型
3. **Boolean** - 布尔类型(true/false)
4. **Undefined** - 未定义
5. **Null** - 空值
6. **Symbol** - 符号(ES6新增)
7. **BigInt** - 大整数(ES2020新增)

以及一种复杂数据类型:
- **Object** - 对象

### 运算符

\`\`\`javascript
// 算术运算符
let sum = 10 + 5;    // 15
let difference = 10 - 5; // 5
let product = 10 * 5; // 50
let quotient = 10 / 5; // 2

// 比较运算符
let isEqual = 10 == 5;   // false
let isStrictEqual = 10 === 5; // false
let isGreater = 10 > 5;  // true

// 逻辑运算符
let andResult = true && false; // false
let orResult = true || false;  // true
let notResult = !true;         // false
\`\`\`

## 函数

函数是JavaScript中的一等公民,可以赋值给变量、作为参数传递或作为返回值。

### 函数声明

\`\`\`javascript
// 函数声明
function greet(name) {
    return "Hello, " + name + "!";
}

// 函数表达式
const greet = function(name) {
    return "Hello, " + name + "!";
};

// 箭头函数 (ES6)
const greet = (name) => {
    return "Hello, " + name + "!";
};

// 简化的箭头函数
const greet = name => "Hello, " + name + "!";
\`\`\`

## 对象和数组

### 对象

对象是键值对的集合。

\`\`\`javascript
const person = {
    firstName: "张",
    lastName: "三",
    age: 30,
    hobbies: ["阅读", "游泳", "编程"],
    fullName: function() {
        return this.firstName + " " + this.lastName;
    }
};

// 访问属性
console.log(person.firstName); // "张"
console.log(person["lastName"]); // "三"
console.log(person.fullName()); // "张 三"
\`\`\`

### 数组

数组是值的有序集合。

\`\`\`javascript
const fruits = ["苹果", "香蕉", "橙子"];

// 访问元素
console.log(fruits[0]); // "苹果"

// 数组方法
fruits.push("葡萄"); // 添加元素到末尾
fruits.pop(); // 移除最后一个元素
fruits.unshift("草莓"); // 添加元素到开头
fruits.shift(); // 移除第一个元素

// 遍历数组
fruits.forEach(function(fruit) {
    console.log(fruit);
});
\`\`\`

## 控制流程

### 条件语句

\`\`\`javascript
// if-else语句
let score = 85;
let grade;

if (score >= 90) {
    grade = "A";
} else if (score >= 80) {
    grade = "B";
} else if (score >= 70) {
    grade = "C";
} else {
    grade = "D";
}

// switch语句
let day = "Monday";
let dayType;

switch (day) {
    case "Saturday":
    case "Sunday":
        dayType = "周末";
        break;
    default:
        dayType = "工作日";
}
\`\`\`

### 循环语句

\`\`\`javascript
// for循环
for (let i = 0; i < 5; i++) {
    console.log(i);
}

// while循环
let i = 0;
while (i < 5) {
    console.log(i);
    i++;
}

// for...of循环 (ES6)
const colors = ["红色", "绿色", "蓝色"];
for (const color of colors) {
    console.log(color);
}
\`\`\`

## DOM操作

文档对象模型(DOM)是HTML文档的编程接口,JavaScript可以通过DOM操作页面元素。

### 选择元素

\`\`\`javascript
// 通过ID选择
const header = document.getElementById("header");

// 通过类名选择
const items = document.getElementsByClassName("item");

// 通过标签名选择
const paragraphs = document.getElementsByTagName("p");

// 使用querySelector
const firstItem = document.querySelector(".item");
const allItems = document.querySelectorAll(".item");
\`\`\`

### 修改元素

\`\`\`javascript
// 修改内容
const element = document.getElementById("myElement");
element.textContent = "新内容";
element.innerHTML = "<strong>加粗内容</strong>";

// 修改样式
element.style.color = "red";
element.style.fontSize = "20px";

// 修改属性
element.setAttribute("data-id", "123");
const id = element.getAttribute("data-id");
\`\`\`

### 事件处理

\`\`\`javascript
// 添加事件监听器
const button = document.getElementById("myButton");
button.addEventListener("click", function() {
    alert("按钮被点击了!");
});

// 事件对象
button.addEventListener("click", function(event) {
    console.log("事件类型: " + event.type);
    console.log("目标元素: " + event.target);
});
\`\`\`

## 异步JavaScript

### 回调函数

\`\`\`javascript
function fetchData(callback) {
    setTimeout(function() {
        const data = { name: "张三", age: 30 };
        callback(data);
    }, 1000);
}

fetchData(function(data) {
    console.log("收到数据: ", data);
});
\`\`\`

### Promise

\`\`\`javascript
function fetchData() {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            const success = true;
            if (success) {
                resolve({ name: "张三", age: 30 });
            } else {
                reject("获取数据失败");
            }
        }, 1000);
    });
}

fetchData()
    .then(function(data) {
        console.log("收到数据: ", data);
    })
    .catch(function(error) {
        console.error("错误: ", error);
    });
\`\`\`

### Async/Await

\`\`\`javascript
async function getData() {
    try {
        const data = await fetchData();
        console.log("收到数据: ", data);
    } catch (error) {
        console.error("错误: ", error);
    }
}

getData();
\`\`\`

## JavaScript框架比较

下面是一个流行的JavaScript框架比较表格:

<table>
<thead>
<tr>
<th>框架名称</th>
<th>特点</th>
<th>学习曲线</th>
<th>性能</th>
<th>适用场景</th>
</tr>
</thead>
<tbody>
<tr>
<td>React</td>
<td>组件化,虚拟DOM,单向数据流</td>
<td>中等</td>
<td>高</td>
<td>大型应用,跨平台开发</td>
</tr>
<tr>
<td>Vue</td>
<td>渐进式,易上手,文档完善</td>
<td>简单</td>
<td>高</td>
<td>中小型应用,快速开发</td>
</tr>
<tr>
<td>Angular</td>
<td>全功能,TypeScript,依赖注入</td>
<td>陡峭</td>
<td>中等</td>
<td>企业级应用,大型团队</td>
</tr>
<tr>
<td>Svelte</td>
<td>编译时优化,无虚拟DOM</td>
<td>简单</td>
<td>非常高</td>
<td>性能敏感应用,小型项目</td>
</tr>
</tbody>
</table>

## 现代JavaScript特性

### 解构赋值

\`\`\`javascript
// 数组解构
const [first, second] = [1, 2, 3];
console.log(first); // 1
console.log(second); // 2

// 对象解构
const { name, age } = { name: "张三", age: 30, city: "北京" };
console.log(name); // "张三"
console.log(age); // 30
\`\`\`

### 模板字符串

\`\`\`javascript
const name = "张三";
const age = 30;
const message = \`大家好,我是\${name},今年\${age}岁。\`;
console.log(message); // "大家好,我是张三,今年30岁。"
\`\`\`

### 扩展运算符

\`\`\`javascript
// 数组扩展
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]

// 对象扩展
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const merged = { ...obj1, ...obj2 }; // { a: 1, b: 2, c: 3, d: 4 }
\`\`\`

## 调试技巧

1. **使用console**:
   \`\`\`javascript
   console.log("普通日志");
   console.warn("警告信息");
   console.error("错误信息");
   console.table([{name: "张三", age: 30}, {name: "李四", age: 25}]);
   \`\`\`

2. **使用debugger语句**:
   \`\`\`javascript
   function problematicFunction() {
       debugger; // 执行到这里会暂停
       // 代码...
   }
   \`\`\`

3. **浏览器开发者工具**:
   - 使用Sources面板设置断点
   - 使用Network面板监控网络请求
   - 使用Performance面板分析性能

## 进一步学习

要深入学习JavaScript,请参考以下资源:

1. [MDN JavaScript指南](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide)
2. [Eloquent JavaScript](https://eloquentjavascript.net/) - 免费的在线书籍
3. [JavaScript.info](https://javascript.info/) - 现代JavaScript教程
4. [W3Schools JavaScript教程](https://www.w3schools.com/js/)

JavaScript是一门功能强大且灵活的语言,通过不断学习和实践,您将能够创建出交互丰富、功能强大的Web应用程序。
                `,
                category: "前端开发",
                tags: ["javascript", "编程", "前端"],
                created: "2023-09-25",
                updated: "2023-10-14",
                views: 102
            },
            "web-security": {
                title: "Web安全基础",
                content: `
# Web安全基础

Web安全是保护网站和Web应用程序免受恶意攻击的实践。本指南将介绍常见的Web安全威胁和防护措施。

## 常见Web安全威胁

### 1. 跨站脚本(XSS)

XSS攻击允许攻击者将恶意脚本注入到其他用户浏览的网页中。

**示例**:
\`\`\`html
<!-- 恶意用户输入 -->
<script>alert('XSS攻击');</script>

<!-- 防护措施:对用户输入进行转义 -->
&lt;script&gt;alert('XSS攻击');&lt;/script&gt;
\`\`\`

### 2. 跨站请求伪造(CSRF)

CSRF攻击诱使用户在不知情的情况下执行非预期的操作。

**防护措施**:
- 使用CSRF令牌
- 检查Referer头
- 使用SameSite Cookie属性

### 3. SQL注入

SQL注入攻击通过在用户输入中插入SQL代码来操纵数据库查询。

**示例**:
\`\`\`sql
-- 恶意输入:' OR '1'='1
-- 原始查询:
SELECT * FROM users WHERE username = '[输入]' AND password = '[密码]'
-- 被操纵的查询:
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '[密码]'
\`\`\`

**防护措施**:
- 使用参数化查询
- 使用ORM(对象关系映射)
- 对用户输入进行验证和转义

### 4. 点击劫持

点击劫持攻击通过透明的iframe覆盖在合法按钮上,诱使用户点击攻击者设置的按钮。

**防护措施**:
- 使用X-Frame-Options HTTP头
- 使用Content Security Policy(CSP)
- 使用Frame Busting JavaScript代码

## 安全防护措施

### 输入验证

对所有用户输入进行严格验证,包括:
- 数据类型检查
- 长度限制
- 格式验证
- 白名单验证

\`\`\`javascript
function validateEmail(email) {
    const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
    return emailRegex.test(email);
}

function sanitizeInput(input) {
    return input
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/\"/g, "&quot;")
        .replace(/'/g, "&#x27;");
}
\`\`\`

### 输出编码

在将数据输出到HTML、JavaScript或URL时,进行适当的编码。

\`\`\`javascript
// HTML编码
function htmlEncode(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
}

// URL编码
function urlEncode(text) {
    return encodeURIComponent(text);
}
\`\`\`

### 身份验证和会话管理

- 使用强密码策略
- 实施多因素认证
- 使用安全的会话管理
- 设置适当的会话超时

\`\`\`javascript
// 密码强度验证
function validatePassword(password) {
    const minLength = 8;
    const hasUpperCase = /[A-Z]/.test(password);
    const hasLowerCase = /[a-z]/.test(password);
    const hasNumbers = /\\d/.test(password);
    const hasSpecialChar = /[!@#$%^&*()_+-\\=\\[\\]{};':"\\\\|,.<>\\/?]/.test(password);
    
    return password.length >= minLength && 
           hasUpperCase && 
           hasLowerCase && 
           hasNumbers && 
           hasSpecialChar;
}
\`\`\`

## 安全头设置

通过HTTP响应头增强安全性:

### Content Security Policy (CSP)

\`\`\`http
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; style-src 'self' 'unsafe-inline'
\`\`\`

### HTTP Strict Transport Security (HSTS)

\`\`\`http
Strict-Transport-Security: max-age=31536000; includeSubDomains
\`\`\`

### X-Content-Type-Options

\`\`\`http
X-Content-Type-Options: nosniff
\`\`\`

### X-Frame-Options

\`\`\`http
X-Frame-Options: DENY
\`\`\`

## 数据加密

### HTTPS

始终使用HTTPS加密数据传输,防止中间人攻击。

### 密码哈希

使用强哈希算法存储密码,如bcrypt、Argon2或PBKDF2。

\`\`\`javascript
// 使用bcrypt哈希密码(Node.js示例)
const bcrypt = require('bcrypt');
const saltRounds = 12;

async function hashPassword(password) {
    const salt = await bcrypt.genSalt(saltRounds);
    const hash = await bcrypt.hash(password, salt);
    return hash;
}

async function verifyPassword(password, hash) {
    return await bcrypt.compare(password, hash);
}
\`\`\`

## 安全测试

### 漏洞扫描

使用自动化工具扫描应用程序漏洞:
- OWASP ZAP
- Nessus
- Burp Suite

### 代码审查

定期进行安全代码审查,查找潜在的安全问题。

### 渗透测试

聘请专业的安全团队进行渗透测试,模拟真实攻击场景。

## 安全开发最佳实践

1. **最小权限原则**:只授予必要的权限
2. **防御性编程**:假设所有输入都是恶意的
3. **安全默认值**:默认配置应该是安全的
4. **错误处理**:不向用户暴露敏感信息
5. **日志和监控**:记录安全事件并实时监控
6. **依赖管理**:定期更新第三方库和框架
7. **安全培训**:对开发团队进行安全培训

## 常见Web安全漏洞对比

下面是一个常见Web安全漏洞的对比表格:

<table>
<thead>
<tr>
<th>漏洞类型</th>
<th>影响程度</th>
<th>修复难度</th>
<th>常见发生场景</th>
<th>防护措施</th>
</tr>
</thead>
<tbody>
<tr>
<td>XSS</td>
<td>高</td>
<td>中等</td>
<td>用户输入显示,评论系统</td>
<td>输入验证,输出编码,CSP</td>
</tr>
<tr>
<td>CSRF</td>
<td>中-高</td>
<td>低</td>
<td>状态更改操作,表单提交</td>
<td>CSRF令牌,SameSite Cookie</td>
</tr>
<tr>
<td>SQL注入</td>
<td>高</td>
<td>低-中等</td>
<td>数据库查询,搜索功能</td>
<td>参数化查询,ORM,输入验证</td>
</tr>
<tr>
<td>点击劫持</td>
<td>中</td>
<td>低</td>
<td>社交媒体,广告</td>
<td>X-Frame-Options,Frame Busting</td>
</tr>
<tr>
<td>文件上传漏洞</td>
<td>高</td>
<td>中等</td>
<td>文件上传功能</td>
<td>文件类型验证,隔离存储</td>
</tr>
<tr>
<td>安全配置错误</td>
<td>中-高</td>
<td>低</td>
<td>服务器配置,默认设置</td>
<td>安全配置检查,自动化扫描</td>
</tr>
</tbody>
</table>

## 安全工具和资源

### 安全工具

1. **OWASP ZAP** - 免费的Web应用安全扫描器
2. **Burp Suite** - 功能强大的Web安全测试工具
3. **Nessus** - 漏洞扫描工具
4. **Metasploit** - 渗透测试框架
5. **Nmap** - 网络发现和安全审计工具

### 安全资源

1. [OWASP(开放Web应用安全项目)](https://owasp.org/) - Web安全权威资源
2. [SANS Internet Storm Center](https://isc.sans.edu/) - 互联网安全威胁信息
3. [CVE(通用漏洞披露)](https://cve.mitre.org/) - 公开的网络安全漏洞数据库
4. [Security Headers](https://securityheaders.com/) - 检查网站安全头的工具

## 安全事件响应

即使采取了所有预防措施,安全事件仍可能发生。制定应急响应计划至关重要:

1. **检测和识别**:及时发现安全事件
2. **遏制**:限制攻击的影响范围
3. **根除**:消除攻击原因
4. **恢复**:恢复正常运营
5. **事后分析**:总结经验教训,改进安全措施

## 结论

Web安全是一个持续的过程,而不是一次性的任务。通过实施多层防御策略、定期安全测试和持续监控,可以显著降低Web应用程序的安全风险。

记住,安全不是产品,而是一个过程。保持警惕,持续学习新的安全威胁和防护技术,是保护Web应用程序安全的关键。
                `,
                category: "安全",
                tags: ["安全", "web", "防护"],
                created: "2023-10-05",
                updated: "2023-10-18",
                views: 58
            }
        };

        // 初始化应用
        document.addEventListener('DOMContentLoaded', function() {
            // 从localStorage加载文章数据
            loadArticlesFromStorage();
            
            // 设置事件监听器
            document.getElementById('home-link').addEventListener('click', showHome);
            document.getElementById('create-link').addEventListener('click', showCreateForm);
            document.getElementById('about-link').addEventListener('click', showAbout);
            document.getElementById('search-input').addEventListener('input', handleSearch);
            
            // 显示首页
            showHome();
            
            // 更新侧边栏
            updateSidebar();
        });

        // 从localStorage加载文章
        function loadArticlesFromStorage() {
            const storedArticles = localStorage.getItem('wikiArticles');
            if (storedArticles) {
                const parsedArticles = JSON.parse(storedArticles);
                Object.assign(wikiArticles, parsedArticles);
            } else {
                // 首次使用,保存默认文章到localStorage
                saveArticlesToStorage();
            }
        }

        // 保存文章到localStorage
        function saveArticlesToStorage() {
            localStorage.setItem('wikiArticles', JSON.stringify(wikiArticles));
        }

        // 显示首页
        function showHome() {
            const contentArea = document.getElementById('content-area');
            
            let html = `
                <div class="article-header">
                    <h1>Wiki文章列表</h1>
                    <p class="article-meta">共 ${Object.keys(wikiArticles).length} 篇文章</p>
                </div>
                <div class="articles-grid">
            `;
            
            // 按更新时间排序
            const sortedArticles = Object.entries(wikiArticles).sort((a, b) => {
                return new Date(b[1].updated) - new Date(a[1].updated);
            });
            
            sortedArticles.forEach(([key, article]) => {
                html += `
                    <div class="article-card" data-article="${key}">
                        <div class="article-card-content">
                            <h3>${article.title}</h3>
                            <p>${article.content.substring(0, 100)}...</p>
                            <div class="meta">
                                <span>分类: ${article.category}</span> | 
                                <span>更新: ${formatDate(article.updated)}</span> | 
                                <span>浏览: ${article.views}次</span>
                            </div>
                        </div>
                    </div>
                `;
            });
            
            html += `</div>`;
            
            contentArea.innerHTML = html;
            
            // 添加文章卡片点击事件
            document.querySelectorAll('.article-card').forEach(card => {
                card.addEventListener('click', function() {
                    const articleKey = this.getAttribute('data-article');
                    showArticle(articleKey);
                });
            });
        }

        // 显示文章
        function showArticle(key) {
            if (!wikiArticles[key]) {
                showError('文章不存在');
                return;
            }
            
            // 增加浏览次数
            wikiArticles[key].views++;
            saveArticlesToStorage();
            
            const article = wikiArticles[key];
            const contentArea = document.getElementById('content-area');
            
            let html = `
                <div class="article-header">
                    <h1>${article.title}</h1>
                    <div class="article-meta">
                        分类: ${article.category} | 
                        创建: ${formatDate(article.created)} | 
                        更新: ${formatDate(article.updated)} | 
                        浏览: ${article.views}次
                    </div>
                </div>
                <div class="article-content">
                    ${renderMarkdown(article.content)}
                </div>
                <div class="article-actions">
                    <button class="btn btn-primary" id="edit-btn">编辑</button>
                    <button class="btn btn-danger" id="delete-btn">删除</button>
                </div>
            `;
            
            contentArea.innerHTML = html;
            
            // 添加编辑和删除按钮事件
            document.getElementById('edit-btn').addEventListener('click', function() {
                showEditForm(key);
            });
            
            document.getElementById('delete-btn').addEventListener('click', function() {
                if (confirm(`确定要删除文章 "${article.title}" 吗?`)) {
                    deleteArticle(key);
                }
            });
        }

        // 显示编辑表单
        function showEditForm(key) {
            const article = wikiArticles[key];
            const contentArea = document.getElementById('content-area');
            
            let html = `
                <div class="article-header">
                    <h1>编辑文章: ${article.title}</h1>
                </div>
                <form class="edit-form" id="edit-form">
                    <input type="text" id="article-title" value="${article.title}" placeholder="文章标题" required>
                    <textarea id="article-content" placeholder="文章内容(支持Markdown语法)" required>${article.content}</textarea>
                    <div>
                        <label for="article-category">分类:</label>
                        <input type="text" id="article-category" value="${article.category}" required>
                    </div>
                    <div>
                        <label for="article-tags">标签(用逗号分隔):</label>
                        <input type="text" id="article-tags" value="${article.tags.join(', ')}">
                    </div>
                    <div class="article-actions">
                        <button type="submit" class="btn btn-primary">保存</button>
                        <button type="button" class="btn btn-secondary" id="cancel-edit">取消</button>
                    </div>
                </form>
            `;
            
            contentArea.innerHTML = html;
            
            // 添加表单提交事件
            document.getElementById('edit-form').addEventListener('submit', function(e) {
                e.preventDefault();
                saveArticle(key);
            });
            
            // 添加取消按钮事件
            document.getElementById('cancel-edit').addEventListener('click', function() {
                showArticle(key);
            });
        }

        // 显示创建表单
        function showCreateForm() {
            const contentArea = document.getElementById('content-area');
            
            let html = `
                <div class="article-header">
                    <h1>创建新文章</h1>
                </div>
                <form class="edit-form" id="create-form">
                    <input type="text" id="article-key" placeholder="文章标识(英文,用于URL)" required>
                    <input type="text" id="article-title" placeholder="文章标题" required>
                    <textarea id="article-content" placeholder="文章内容(支持Markdown语法)" required></textarea>
                    <div>
                        <label for="article-category">分类:</label>
                        <input type="text" id="article-category" required>
                    </div>
                    <div>
                        <label for="article-tags">标签(用逗号分隔):</label>
                        <input type="text" id="article-tags">
                    </div>
                    <div class="article-actions">
                        <button type="submit" class="btn btn-primary">创建</button>
                        <button type="button" class="btn btn-secondary" id="cancel-create">取消</button>
                    </div>
                </form>
            `;
            
            contentArea.innerHTML = html;
            
            // 添加表单提交事件
            document.getElementById('create-form').addEventListener('submit', function(e) {
                e.preventDefault();
                createArticle();
            });
            
            // 添加取消按钮事件
            document.getElementById('cancel-create').addEventListener('click', function() {
                showHome();
            });
        }

        // 显示关于页面
        function showAbout() {
            const contentArea = document.getElementById('content-area');
            
            const html = `
                <div class="article-header">
                    <h1>关于简易Wiki系统</h1>
                </div>
                <div class="article-content">
                    <h2>系统介绍</h2>
                    <p>这是一个基于纯前端技术(HTML/CSS/JavaScript)实现的简易Wiki系统,无需后端支持,所有数据存储在浏览器的localStorage中。</p>
                    
                    <h2>功能特点</h2>
                    <ul>
                        <li><strong>文章管理</strong>:创建、编辑、删除和查看Wiki文章</li>
                        <li><strong>Markdown支持</strong>:使用Markdown语法格式化文章内容</li>
                        <li><strong>搜索功能</strong>:通过关键词搜索文章标题和内容</li>
                        <li><strong>分类管理</strong>:自动根据文章分类组织内容</li>
                        <li><strong>响应式设计</strong>:适配各种屏幕尺寸的设备</li>
                        <li><strong>本地存储</strong>:使用localStorage持久化数据</li>
                    </ul>
                    
                    <h2>技术栈</h2>
                    <table>
                        <thead>
                            <tr>
                                <th>技术</th>
                                <th>用途</th>
                                <th>特点</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>HTML5</td>
                                <td>页面结构和内容</td>
                                <td>语义化标签,良好的可访问性</td>
                            </tr>
                            <tr>
                                <td>CSS3</td>
                                <td>页面样式和布局</td>
                                <td>Flexbox/Grid布局,响应式设计</td>
                            </tr>
                            <tr>
                                <td>JavaScript (ES6+)</td>
                                <td>交互逻辑和数据管理</td>
                                <td>现代语法,localStorage API</td>
                            </tr>
                            <tr>
                                <td>Markdown</td>
                                <td>内容格式化</td>
                                <td>简单易学,专注于内容</td>
                            </tr>
                        </tbody>
                    </table>
                    
                    <h2>使用说明</h2>
                    <ol>
                        <li>在首页可以浏览所有已创建的Wiki文章</li>
                        <li>点击"创建文章"可以添加新的Wiki页面</li>
                        <li>在文章页面点击"编辑"可以修改文章内容</li>
                        <li>使用搜索框可以快速查找特定内容</li>
                        <li>侧边栏显示文章分类和热门文章</li>
                    </ol>
                    
                    <h2>注意事项</h2>
                    <div class="alert alert-success">
                        <p><strong>数据存储</strong>:所有文章数据存储在浏览器的localStorage中,清除浏览器数据会导致文章丢失。</p>
                        <p><strong>浏览器兼容</strong>:系统需要现代浏览器支持,建议使用Chrome、Firefox、Safari或Edge的最新版本。</p>
                        <p><strong>Markdown语法</strong>:文章内容支持基本的Markdown语法,包括标题、列表、链接、代码块等。</p>
                    </div>
                    
                    <h2>进一步开发</h2>
                    <p>这个简易Wiki系统可以进一步扩展以下功能:</p>
                    <ul>
                        <li>添加用户认证和权限管理</li>
                        <li>支持文章版本历史和回滚</li>
                        <li>添加图片上传和媒体管理</li>
                        <li>实现文章导出和备份功能</li>
                        <li>添加评论和讨论区</li>
                    </ul>
                    
                    <blockquote>
                        <p>这个项目展示了如何使用纯前端技术构建功能完整的Web应用,适合学习前端开发和理解Web应用的基本原理。</p>
                    </blockquote>
                </div>
            `;
            
            contentArea.innerHTML = html;
        }

        // 保存文章
        function saveArticle(key) {
            const title = document.getElementById('article-title').value;
            const content = document.getElementById('article-content').value;
            const category = document.getElementById('article-category').value;
            const tags = document.getElementById('article-tags').value.split(',').map(tag => tag.trim());
            
            wikiArticles[key].title = title;
            wikiArticles[key].content = content;
            wikiArticles[key].category = category;
            wikiArticles[key].tags = tags;
            wikiArticles[key].updated = new Date().toISOString().split('T')[0];
            
            saveArticlesToStorage();
            updateSidebar();
            showArticle(key);
            
            showAlert('文章已成功更新!', 'success');
        }

        // 创建文章
        function createArticle() {
            const key = document.getElementById('article-key').value;
            const title = document.getElementById('article-title').value;
            const content = document.getElementById('article-content').value;
            const category = document.getElementById('article-category').value;
            const tags = document.getElementById('article-tags').value.split(',').map(tag => tag.trim());
            
            if (wikiArticles[key]) {
                showAlert('文章标识已存在,请使用其他标识!', 'error');
                return;
            }
            
            const today = new Date().toISOString().split('T')[0];
            
            wikiArticles[key] = {
                title: title,
                content: content,
                category: category,
                tags: tags,
                created: today,
                updated: today,
                views: 0
            };
            
            saveArticlesToStorage();
            updateSidebar();
            showArticle(key);
            
            showAlert('文章已成功创建!', 'success');
        }

        // 删除文章
        function deleteArticle(key) {
            if (key === 'home') {
                showAlert('不能删除首页文章!', 'error');
                return;
            }
            
            delete wikiArticles[key];
            saveArticlesToStorage();
            updateSidebar();
            showHome();
            
            showAlert('文章已成功删除!', 'success');
        }

        // 处理搜索
        function handleSearch() {
            const query = document.getElementById('search-input').value.toLowerCase();
            
            if (query.length < 2) {
                showHome();
                return;
            }
            
            const contentArea = document.getElementById('content-area');
            
            let html = `
                <div class="article-header">
                    <h1>搜索结果: "${query}"</h1>
                    <p class="article-meta">找到 ${Object.keys(wikiArticles).filter(key => 
                        wikiArticles[key].title.toLowerCase().includes(query) || 
                        wikiArticles[key].content.toLowerCase().includes(query) ||
                        wikiArticles[key].tags.some(tag => tag.toLowerCase().includes(query))
                    ).length} 篇相关文章</p>
                </div>
                <div class="articles-grid">
            `;
            
            const results = Object.entries(wikiArticles).filter(([key, article]) => {
                return article.title.toLowerCase().includes(query) || 
                       article.content.toLowerCase().includes(query) ||
                       article.tags.some(tag => tag.toLowerCase().includes(query));
            });
            
            if (results.length === 0) {
                html += `<p>没有找到相关文章。</p>`;
            } else {
                results.forEach(([key, article]) => {
                    html += `
                        <div class="article-card" data-article="${key}">
                            <div class="article-card-content">
                                <h3>${article.title}</h3>
                                <p>${article.content.substring(0, 100)}...</p>
                                <div class="meta">
                                    <span>分类: ${article.category}</span> | 
                                    <span>更新: ${formatDate(article.updated)}</span> | 
                                    <span>浏览: ${article.views}次</span>
                                </div>
                            </div>
                        </div>
                    `;
                });
            }
            
            html += `</div>`;
            
            contentArea.innerHTML = html;
            
            // 添加文章卡片点击事件
            document.querySelectorAll('.article-card').forEach(card => {
                card.addEventListener('click', function() {
                    const articleKey = this.getAttribute('data-article');
                    showArticle(articleKey);
                });
            });
        }

        // 更新侧边栏
        function updateSidebar() {
            const categoryList = document.getElementById('category-list');
            const popularArticles = document.getElementById('popular-articles');
            
            // 更新分类列表
            const categories = [...new Set(Object.values(wikiArticles).map(article => article.category))];
            categoryList.innerHTML = '';
            categories.forEach(category => {
                const li = document.createElement('li');
                li.innerHTML = `<a href="#" class="category-link" data-category="${category}">${category}</a>`;
                categoryList.appendChild(li);
            });
            
            // 更新热门文章
            const sortedByViews = Object.entries(wikiArticles)
                .sort((a, b) => b[1].views - a[1].views)
                .slice(0, 5);
            
            popularArticles.innerHTML = '';
            sortedByViews.forEach(([key, article]) => {
                const li = document.createElement('li');
                li.innerHTML = `<a href="#" class="article-link" data-article="${key}">${article.title}</a>`;
                popularArticles.appendChild(li);
            });
            
            // 添加分类链接事件
            document.querySelectorAll('.category-link').forEach(link => {
                link.addEventListener('click', function(e) {
                    e.preventDefault();
                    const category = this.getAttribute('data-category');
                    filterByCategory(category);
                });
            });
            
            // 添加文章链接事件
            document.querySelectorAll('.article-link').forEach(link => {
                link.addEventListener('click', function(e) {
                    e.preventDefault();
                    const articleKey = this.getAttribute('data-article');
                    showArticle(articleKey);
                });
            });
        }

        // 按分类筛选
        function filterByCategory(category) {
            const contentArea = document.getElementById('content-area');
            
            let html = `
                <div class="article-header">
                    <h1>分类: ${category}</h1>
                    <p class="article-meta">共 ${Object.values(wikiArticles).filter(article => article.category === category).length} 篇文章</p>
                </div>
                <div class="articles-grid">
            `;
            
            const categoryArticles = Object.entries(wikiArticles).filter(([key, article]) => 
                article.category === category
            );
            
            categoryArticles.forEach(([key, article]) => {
                html += `
                    <div class="article-card" data-article="${key}">
                        <div class="article-card-content">
                            <h3>${article.title}</h3>
                            <p>${article.content.substring(0, 100)}...</p>
                            <div class="meta">
                                <span>分类: ${article.category}</span> | 
                                <span>更新: ${formatDate(article.updated)}</span> | 
                                <span>浏览: ${article.views}次</span>
                            </div>
                        </div>
                    </div>
                `;
            });
            
            html += `</div>`;
            
            contentArea.innerHTML = html;
            
            // 添加文章卡片点击事件
            document.querySelectorAll('.article-card').forEach(card => {
                card.addEventListener('click', function() {
                    const articleKey = this.getAttribute('data-article');
                    showArticle(articleKey);
                });
            });
        }

        // 显示错误
        function showError(message) {
            const contentArea = document.getElementById('content-area');
            contentArea.innerHTML = `
                <div class="alert alert-error">
                    <strong>错误:</strong> ${message}
                </div>
                <div class="article-actions">
                    <button class="btn btn-primary" onclick="showHome()">返回首页</button>
                </div>
            `;
        }

        // 显示提示
        function showAlert(message, type) {
            // 移除现有提示
            const existingAlert = document.querySelector('.alert');
            if (existingAlert) {
                existingAlert.remove();
            }
            
            const alert = document.createElement('div');
            alert.className = `alert alert-${type}`;
            alert.textContent = message;
            
            document.querySelector('.container').insertBefore(alert, document.querySelector('.search-container'));
            
            // 3秒后自动移除
            setTimeout(() => {
                alert.remove();
            }, 3000);
        }

        // 格式化日期
        function formatDate(dateString) {
            const date = new Date(dateString);
            return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;
        }

        // 简化的Markdown渲染
        function renderMarkdown(text) {
            // 处理标题
            text = text.replace(/^# (.*$)/gm, '<h1>$1</h1>');
            text = text.replace(/^## (.*$)/gm, '<h2>$1</h2>');
            text = text.replace(/^### (.*$)/gm, '<h3>$1</h3>');
            
            // 处理粗体
            text = text.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
            text = text.replace(/\*(.*?)\*/g, '<em>$1</em>');
            
            // 处理代码块
            text = text.replace(/```([\s\S]*?)```/g, '<pre><code>$1</code></pre>');
            text = text.replace(/`(.*?)`/g, '<code>$1</code>');
            
            // 处理链接
            text = text.replace(/\[(.*?)\]\((.*?)\)/g, '<a href="$2" target="_blank">$1</a>');
            
            // 处理列表
            text = text.replace(/^\s*\- (.*$)/gm, '<li>$1</li>');
            text = text.replace(/(<li>.*<\/li>)/s, '<ul>$1</ul>');
            
            text = text.replace(/^\s*\d+\. (.*$)/gm, '<li>$1</li>');
            text = text.replace(/(<li>.*<\/li>)/s, '<ol>$1</ol>');
            
            // 处理段落
            text = text.replace(/\n\n/g, '</p><p>');
            text = '<p>' + text + '</p>';
            
            // 处理表格
            text = text.replace(/\|(.*)\|/g, function(match) {
                if (match.includes('---')) {
                    return ''; // 跳过表头分隔线
                }
                return '<tr>' + match.split('|').slice(1, -1).map(cell => 
                    `<td>${cell.trim()}</td>`
                ).join('') + '</tr>';
            });
            
            text = text.replace(/(<tr>.*<\/tr>)/s, function(match) {
                return '<table>' + match + '</table>';
            });
            
            // 处理引用
            text = text.replace(/^> (.*$)/gm, '<blockquote>$1</blockquote>');
            
            return text;
        }
    </script>
</body>
</html>

系统功能详解

这个简易Wiki系统实现了以下核心功能:

1. 文章管理

  • 创建新文章
  • 编辑现有文章
  • 删除文章
  • 查看文章详情

2. 内容展示

  • 使用Markdown语法格式化内容
  • 支持表格、代码块、链接等丰富格式
  • 响应式设计,适配各种设备

3. 搜索和分类

  • 全文搜索功能
  • 按分类筛选文章
  • 热门文章推荐

4. 数据持久化

  • 使用localStorage存储数据
  • 文章浏览计数
  • 更新日期跟踪

技术实现要点

  1. 纯前端实现:无需后端支持,所有功能在浏览器中完成
  2. 响应式设计:使用CSS Grid和Flexbox实现自适应布局
  3. Markdown渲染:实现了简化的Markdown到HTML的转换
  4. 本地存储:使用localStorage API实现数据持久化
  5. 模块化设计:功能模块清晰分离,便于维护和扩展

扩展建议

这个简易Wiki系统还可以进一步扩展:

  • 添加用户认证和权限管理
  • 实现文章版本历史
  • 添加图片上传功能
  • 支持文章导出和备份
  • 添加评论和讨论功能
相关推荐
景早9 小时前
vue 记事本案例详解
前端·javascript·vue.js
格林威9 小时前
AOI在产品质量检测制造领域的应用
人工智能·数码相机·计算机网络·计算机视觉·目标跟踪·视觉检测·制造
短视频矩阵源码定制10 小时前
矩阵系统源码推荐:技术架构与功能完备性深度解析
java·人工智能·矩阵·架构
彩云回10 小时前
多维尺度分析法(MDS)
人工智能·机器学习·1024程序员节
Rock_yzh10 小时前
AI学习日记——Transformer的架构:编码器与解码器
人工智能·深度学习·神经网络·学习·transformer
rengang6610 小时前
Spring AI Alibaba 框架使用示例总体介绍
java·人工智能·spring·spring ai·ai应用编程
wangjialelele10 小时前
Qt中的常用组件:QWidget篇
开发语言·前端·c++·qt
乔冠宇11 小时前
vue需要学习的点
前端·vue.js·学习
FreeBuf_11 小时前
新型Agent感知伪装技术利用OpenAI ChatGPT Atlas浏览器传播虚假内容
人工智能·chatgpt