当然, 我们可以在主功能菜单中添加选择模板和设计新模板的功能按钮。这将使用户更容易自定义他们的博客外观。让我们来实现这个功能:

  1. 首先, 更新 src/components/Blog.tsx 文件, 在主导航中添加新的按钮:
import React from 'react'
import { Theme } from '../types'
import { ThemeSelector } from './ThemeSelector'
 
interface BlogProps {
  posts: Post[]
  user: User | null
  theme: Theme
  availableThemes: string[]
}
 
export const Blog: React.FC<BlogProps> = ({ posts, user, theme, availableThemes }) => {
  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}>
          <h1 className={`text-4xl font-bold ${theme.colors.primary}`}>My Blog</h1>
          <nav className="mt-4 space-x-4">
            <a href="/" className={theme.colors.primary}>Home</a>
            <a href="/stats" className={theme.colors.primary}>Statistics</a>
            <a href="/select-theme" className={theme.colors.primary}>Select Theme</a>
            <a href="/design-theme" className={theme.colors.primary}>Design New Theme</a>
            {user ? (
              <span>Welcome, {user.name}! <a href="/logout" className={theme.colors.secondary}>Logout</a></span>
            ) : (
              <a href="/login" className={theme.colors.primary}>Login</a>
            )}
          </nav>
        </div>
      </header>
      {/* 其余的组件内容保持不变 */}
    </div>
  )
}
  1. 创建一个新的组件 src/components/ThemeSelector.tsx 用于主题选择:
import React from 'react'
import { Theme } from '../types'
 
interface ThemeSelectorProps {
  themes: Theme[]
  currentTheme: string
  onThemeChange: (themeName: string) => void
}
 
export const ThemeSelector: React.FC<ThemeSelectorProps> = ({ themes, currentTheme, onThemeChange }) => {
  return (
    <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
      {themes.map((theme) => (
        <div
          key={theme.name}
          className={`p-4 rounded-lg cursor-pointer ${
            theme.name === currentTheme ? 'ring-2 ring-blue-500' : ''
          }`}
          style={{ backgroundColor: theme.colors.background }}
          onClick={() => onThemeChange(theme.name)}
        >
          <h3 className="text-lg font-semibold" style={{ color: theme.colors.primary }}>
            {theme.name}
          </h3>
          <div className="mt-2 flex space-x-2">
            <div className="w-6 h-6 rounded-full" style={{ backgroundColor: theme.colors.primary }}></div>
            <div className="w-6 h-6 rounded-full" style={{ backgroundColor: theme.colors.secondary }}></div>
            <div className="w-6 h-6 rounded-full" style={{ backgroundColor: theme.colors.accent }}></div>
          </div>
        </div>
      ))}
    </div>
  )
}
  1. 创建一个新的组件 src/components/ThemeDesigner.tsx 用于设计新主题:
import React, { useState } from 'react'
import { Theme } from '../types'
 
interface ThemeDesignerProps {
  onSave: (theme: Theme) => void
}
 
export const ThemeDesigner: React.FC<ThemeDesignerProps> = ({ onSave }) => {
  const [themeName, setThemeName] = useState('')
  const [backgroundColor, setBackgroundColor] = useState('#ffffff')
  const [textColor, setTextColor] = useState('#000000')
  const [primaryColor, setPrimaryColor] = useState('#3b82f6')
  const [secondaryColor, setSecondaryColor] = useState (' #6b7280 ')
  const [accentColor, setAccentColor] = useState (' #f59e0b ')
 
  const handleSave = () => {
    const newTheme: Theme = {
      name: themeName,
      colors: {
        background: `bg-[${backgroundColor}]`,
        text: `text-[${textColor}]`,
        primary: `text-[${primaryColor}]`,
        secondary: `text-[${secondaryColor}]`,
        accent: `text-[${accentColor}]`,
      },
      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-[${primaryColor}] text-white rounded hover:bg-opacity-90`,
        input: `px-3 py-2 border border-[${secondaryColor}] rounded focus:ring-2 focus:ring-[${primaryColor}]`,
        card: `bg-[${backgroundColor}] shadow rounded-lg overflow-hidden`,
      }
    }
    onSave(newTheme)
  }
 
  return (
    <div className="space-y-4">
      <input
        type="text"
        placeholder="Theme Name"
        value={themeName}
        onChange={(e) => setThemeName(e.target.value)}
        className="w-full px-3 py-2 border rounded"
      />
      <div>
        <label>Background Color:</label>
        <input
          type="color"
          value={backgroundColor}
          onChange={(e) => setBackgroundColor(e.target.value)}
        />
      </div>
      <div>
        <label>Text Color:</label>
        <input
          type="color"
          value={textColor}
          onChange={(e) => setTextColor(e.target.value)}
        />
      </div>
      <div>
        <label>Primary Color:</label>
        <input
          type="color"
          value={primaryColor}
          onChange={(e) => setPrimaryColor(e.target.value)}
        />
      </div>
      <div>
        <label>Secondary Color:</label>
        <input
          type="color"
          value={secondaryColor}
          onChange={(e) => setSecondaryColor(e.target.value)}
        />
      </div>
      <div>
        <label>Accent Color:</label>
        <input
          type="color"
          value={accentColor}
          onChange={(e) => setAccentColor(e.target.value)}
        />
      </div>
      <button onClick={handleSave} className="px-4 py-2 bg-blue-500 text-white rounded">
        Save Theme
      </button>
    </div>
  )
}
  1. 更新 src/index.ts 以添加新的路由:
import { Elysia } from 'elysia'
import { html } from '@elysiajs/html'
import { staticPlugin } from '@elysiajs/static'
import { renderToString } from 'react-dom/server'
import { Blog } from './components/Blog'
import { ThemeSelector } from './components/ThemeSelector'
import { ThemeDesigner } from './components/ThemeDesigner'
Import { themes } from './themes'
 
// ... 其他导入和设置
 
const app = new Elysia()
  .use(html())
  .use(staticPlugin())
  
  // ... 其他中间件和路由
 
  .get ('/select-theme', ({ html }) => {
    const themeSelector = renderToString(
      <ThemeSelector
        themes={Object.values(themes)}
        currentTheme={cookie.theme || 'classic'}
        onThemeChange={(themeName) => {
          // 这里应该是客户端JavaScript,用于更新主题
          // 在服务端渲染中,我们可以提供一个表单来提交主题更改
        }}
      />
    )
 
    return html(`
      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Select Theme</title>
          <link rel="stylesheet" href="/uno.css">
        </head>
        <body>
          <div class="container mx-auto p-4">
            <h1 class="text-2xl font-bold mb-4">Select Theme</h1>
            <form method="POST" action="/change-theme">
              ${themeSelector}
              <button type="submit" class="mt-4 px-4 py-2 bg-blue-500 text-white rounded">
                Apply Theme
              </button>
            </form>
          </div>
        </body>
      </html>
    `)
  })
 
  .get('/design-theme', ({ html }) => {
    const themeDesigner = renderToString(
      <ThemeDesigner
        onSave={(theme) => {
          // 这里应该是客户端JavaScript,用于保存新主题
          // 在服务端渲染中,我们可以提供一个表单来提交新主题
        }}
      />
    )
 
    return html(`
      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Design New Theme</title>
          <link rel="stylesheet" href="/uno.css">
        </head>
        <body>
          <div class="container mx-auto p-4">
            <h1 class="text-2xl font-bold mb-4">Design New Theme</h1>
            <form method="POST" action="/save-theme">
              ${themeDesigner}
            </form>
          </div>
        </body>
      </html>
    `)
  })
 
  .post('/change-theme', ({ body, set, cookie }) => {
    const { theme } = body as { theme: string }
    cookie.theme = theme
    set.redirect = '/'
  })
 
  .post('/save-theme', ({ body, set }) => {
    // 这里应该处理保存新主题的逻辑
    // 可能需要将新主题保存到数据库或文件系统
    set.redirect = '/select-theme'
  })
 
  .listen(3000)
  1. 更新 src/themes/index.ts 文件以导出所有主题:
import classicTheme from './classic'
import modernDarkTheme from './modernDark'
import natureGreenTheme from './natureGreen'
import vibrantTheme from './vibrant'
 
export const themes = {
  classic: classicTheme,
  modernDark: modernDarkTheme,
  natureGreen: natureGreenTheme,
  Vibrant: vibrantTheme,
}

这些更改添加了以下功能:

  1. 在主导航中添加了”Select Theme”和”Design New Theme”按钮。
  2. 创建了一个主题选择器页面, 用户可以在预定义的主题中选择。
  3. 创建了一个主题设计器页面, 用户可以创建自定义主题。
  4. 添加了处理主题更改和保存新主题的路由。

要使这个功能完全工作, 你还需要:

  • 实现保存自定义主题的后端逻辑。
  • 添加客户端 JavaScript 以增强用户体验, 例如实时预览主题更改。
  • 考虑添加主题预览功能, 让用户在应用主题之前可以看到效果。
  • 实现主题编辑功能, 允许用户修改现有主题。
  • 添加主题分享功能, 让用户可以与他人分享自己创建的主题。

这些添加的功能大大增强了博客系统的可定制性, 让用户可以更容易地个性化他们的博客外观。