好的,让我们针对用户体验提升的四个方面进行优化:夜间模式切换、全站搜索功能、文章推荐系统和阅读进度指示器。这些功能将显著提升用户的使用体验。

  1. 夜间模式切换

首先,我们需要创建一个夜间模式的主题:

// src/themes/nightMode.ts
export default {
  name: 'Night Mode',
  colors: {
    background: 'bg-gray-900',
    text: 'text-gray-200',
    primary: 'text-blue-400',
    secondary: 'text-gray-400',
    accent: 'text-yellow-400',
  },
  layout: {
    container: 'max-w-4xl mx-auto px-4',
    header: 'py-6',
    main: 'py-8',
    footer: 'py-6 text-center',
  },
  components: {
    button: 'px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700',
    input: 'px-3 py-2 bg-gray-800 border border-gray-700 rounded focus:ring-2 focus:ring-blue-500',
    card: 'bg-gray-800 shadow rounded-lg overflow-hidden',
  }
}

然后,更新 Blog 组件以包含夜间模式切换按钮:

// src/components/Blog.tsx
import React, { useState, useEffect } from 'react'
import { Theme } from '../types'
 
interface BlogProps {
  // ... 其他 props
  initialTheme: Theme
}
 
export const Blog: React.FC<BlogProps> = ({ /* 其他 props */, initialTheme }) => {
  const [theme, setTheme] = useState(initialTheme)
 
  const toggleNightMode = () => {
    const newTheme = theme.name === 'Night Mode' ? themes.default : themes.nightMode
    setTheme(newTheme)
    document.cookie = `theme=${newTheme.name};path=/;max-age=31536000`
  }
 
  return (
    <div className={`min-h-screen flex flex-col ${theme.colors.background} ${theme.colors.text}`}>
      <header className={theme.layout.header}>
        <div className={theme.layout.container}>
          {/* ... 其他头部内容 */}
          <button onClick={toggleNightMode} className={theme.components.button}>
            {theme.name === 'Night Mode' ? '☀️ Light Mode' : '🌙 Night Mode'}
          </button>
        </div>
      </header>
      {/* ... 其他内容 */}
    </div>
  )
}
  1. 全站搜索功能

为了实现全站搜索,我们需要创建一个搜索 API 和搜索组件:

// src/index.ts
import { like } from 'drizzle-orm'
 
// ... 其他导入
 
app.get('/api/search', async ({ query }) => {
  const { q } = query
  if (!q) return []
 
  const searchResults = await db.select()
    .from(posts)
    .where(or(
      like(posts.title, `%${q}%`),
      like(posts.content, `%${q}%`)
    ))
    .limit(10)
    .all()
 
  return searchResults
})

创建搜索组件:

// src/components/Search.tsx
import React, { useState } from 'react'
import { Theme } from '../types'
 
interface SearchProps {
  theme: Theme
}
 
export const Search: React.FC<SearchProps> = ({ theme }) => {
  const [query, setQuery] = useState('')
  const [results, setResults] = useState([])
 
  const handleSearch = async () => {
    const response = await fetch(`/api/search?q=${encodeURIComponent(query)}`)
    const data = await response.json()
    setResults(data)
  }
 
  return (
    <div>
      <input
        type="text"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Search..."
        className={theme.components.input}
      />
      <button onClick={handleSearch} className={theme.components.button}>Search</button>
      <ul className="mt-4">
        {results.map((result) => (
          <li key={result.id} className={theme.components.card + ' p-4 mb-2'}>
            <a href={`/post/${result.id}`} className={theme.colors.primary}>
              {result.title}
            </a>
          </li>
        ))}
      </ul>
    </div>
  )
}
  1. 文章推荐系统

为了实现简单的文章推荐,我们可以基于标签相似度来推荐文章:

// src/index.ts
app.get('/api/post/:id/recommendations', async ({ params }) => {
  const postId = parseInt(params.id)
  
  // 获取当前文章的标签
  const currentPostTags = await db.select()
    .from(postTags)
    .where(eq(postTags.postId, postId))
    .all()
 
  const tagIds = currentPostTags.map(pt => pt.tagId)
 
  // 查找具有相同标签的其他文章
  const recommendedPosts = await db.select({
    id: posts.id,
    title: posts.title,
    tagCount: sql`count(${postTags.tagId})`.as('tag_count'),
  })
    .from(posts)
    .innerJoin(postTags, eq(posts.id, postTags.postId))
    .where(and(
      inArray(postTags.tagId, tagIds),
      ne(posts.id, postId)
    ))
    .groupBy(posts.id)
    .orderBy(desc(sql`tag_count`), desc(posts.createdAt))
    .limit(5)
    .all()
 
  return recommendedPosts
})

然后在文章页面中显示推荐文章:

// src/components/PostDetail.tsx
import React, { useEffect, useState } from 'react'
import { Theme, Post } from '../types'
 
interface PostDetailProps {
  post: Post
  theme: Theme
}
 
export const PostDetail: React.FC<PostDetailProps> = ({ post, theme }) => {
  const [recommendations, setRecommendations] = useState([])
 
  useEffect(() => {
    fetch(`/api/post/${post.id}/recommendations`)
      .then(res => res.json())
      .then(setRecommendations)
  }, [post.id])
 
  return (
    <div>
      {/* 文章内容 */}
      <h1 className={`text-2xl font-bold ${theme.colors.primary}`}>{post.title}</h1>
      <div className={theme.colors.text}>{post.content}</div>
      
      {/* 推荐文章 */}
      <div className="mt-8">
        <h2 className={`text-xl font-semibold ${theme.colors.secondary}`}>Recommended Articles</h2>
        <ul className="mt-4">
          {recommendations.map((rec) => (
            <li key={rec.id} className={theme.components.card + ' p-4 mb-2'}>
              <a href={`/post/${rec.id}`} className={theme.colors.primary}>
                {rec.title}
              </a>
            </li>
          ))}
        </ul>
      </div>
    </div>
  )
}
  1. 阅读进度指示器

我们可以创建一个阅读进度指示器组件:

// src/components/ReadingProgress.tsx
import React, { useState, useEffect } from 'react'
import { Theme } from '../types'
 
interface ReadingProgressProps {
  theme: Theme
}
 
export const ReadingProgress: React.FC<ReadingProgressProps> = ({ theme }) => {
  const [progress, setProgress] = useState(0)
 
  useEffect(() => {
    const updateProgress = () => {
      const scrollTop = window.scrollY
      const docHeight = document.documentElement.scrollHeight - window.innerHeight
      const scrollPercent = scrollTop / docHeight
      setProgress(scrollPercent * 100)
    }
 
    window.addEventListener('scroll', updateProgress)
    return () => window.removeEventListener('scroll', updateProgress)
  }, [])
 
  return (
    <div className="fixed top-0 left-0 w-full h-1 bg-gray-200">
      <div
        className={`h-full ${theme.colors.primary}`}
        style={{ width: `${progress}%` }}
      ></div>
    </div>
  )
}

然后在 Blog 组件中使用这个进度指示器:

// src/components/Blog.tsx
import { ReadingProgress } from './ReadingProgress'
 
export const Blog: React.FC<BlogProps> = ({ /* 其他 props */ }) => {
  return (
    <div className={`min-h-screen flex flex-col ${theme.colors.background} ${theme.colors.text}`}>
      <ReadingProgress theme={theme} />
      {/* ... 其他内容 */}
    </div>
  )
}

这些优化为博客系统添加了以下功能:

  1. 夜间模式切换:用户可以根据自己的喜好切换明暗主题。
  2. 全站搜索功能:用户可以快速找到感兴趣的文章。
  3. 文章推荐系统:基于标签相似度为用户推荐相关文章,增加用户停留时间。
  4. 阅读进度指示器:为用户提供直观的阅读进度反馈。

要进一步完善这些功能,你可以考虑:

  • 为夜间模式添加自动切换功能,根据用户系统设置或时间自动切换。
  • 改进搜索功能,添加高亮显示搜索词、搜索建议等功能。
  • 优化推荐系统,考虑用户阅读历史、停留时间等因素。
  • 为长文章添加目录功能,配合阅读进度指示器使用。

这些用户体验的优化将使你的博客系统更加用户友好,提高用户满意度和参与度。随着系统的发展,你可能还需要考虑性能优化,如延迟加载、代码分割等技术,以确保在添加新功能的同时保持良好的性能。