HiHuo
首页
博客
手册
工具
关于
首页
博客
手册
工具
关于
  • AI 训练手册

    • AI UI生成系统 - 完整学习手册
    • 项目概述与架构设计
    • 环境搭建与快速开始
    • 核心概念与术语
    • 数据生成系统
    • UI-DSL数据格式详解
    • 数据质量与评估
    • LoRA微调技术
    • 完整的模型训练流程
    • 模型推理与优化
    • PNG图片渲染实现
    • Vue页面渲染系统
    • 多主题支持架构
    • FastAPI服务设计
    • Docker部署实践
    • 生产环境运维
    • 项目实战案例
    • 性能优化指南
    • 扩展开发指南
    • API参考文档
    • 配置参数说明
    • 故障排查指南

多主题支持架构

1. 概述

多主题支持是AI UI生成系统的核心设计特性,通过统一的主题配置系统,实现一套代码支持多种视觉风格。本章详细介绍主题系统的架构设计、配置结构、实现机制和扩展开发,包括三大内置主题(obsidian-gold、silver-white、minimal)的详细解析和自定义主题开发指南。

2. 主题系统架构

2.1 整体架构图

主题配置 -> 主题解析器 -> 渲染引擎 -> 多格式输出
    ↓         ↓          ↓         ↓
ui_tokens.json  ThemeParser  Renderer   PNG/Vue/HTML

2.2 主题系统组件

class ThemeSystem:
    """主题系统核心类"""
    
    def __init__(self, tokens_path: str = "config/ui_tokens.json"):
        """初始化主题系统"""
        self.tokens_path = tokens_path
        self.tokens = self._load_tokens()
        self.themes = self.tokens.get("themes", {})
        self.components = self.tokens.get("components", {})
    
    def _load_tokens(self) -> Dict:
        """加载UI令牌配置"""
        with open(self.tokens_path, 'r', encoding='utf-8') as f:
            return json.load(f)
    
    def get_theme(self, theme_name: str) -> Dict:
        """获取指定主题配置"""
        return self.themes.get(theme_name, self.themes["obsidian-gold"])
    
    def get_component_config(self, component_name: str) -> Dict:
        """获取组件配置"""
        return self.components.get(component_name, {})

3. 主题配置结构

3.1 UI令牌配置文件结构

{
  "themes": {
    "obsidian-gold": {
      "colors": {
        "primary": "#FFD700",
        "secondary": "#B8860B",
        "background": "#0E0E0E",
        "surface": "#1A1A1A",
        "text": "#FFFFFF",
        "text_secondary": "#CCCCCC",
        "border": "#333333",
        "accent": "#FF6B35",
        "success": "#4CAF50",
        "warning": "#FF9800",
        "error": "#F44336"
      },
      "typography": {
        "font_family": "PingFang SC, -apple-system, BlinkMacSystemFont, sans-serif",
        "font_size_base": "16px",
        "font_size_small": "14px",
        "font_size_large": "18px",
        "font_weight_normal": "400",
        "font_weight_bold": "600"
      },
      "spacing": {
        "xs": "4px",
        "sm": "8px",
        "md": "16px",
        "lg": "24px",
        "xl": "32px",
        "xxl": "48px"
      },
      "border_radius": {
        "small": "4px",
        "medium": "8px",
        "large": "12px",
        "round": "50%"
      },
      "shadows": {
        "small": "0 1px 3px rgba(0, 0, 0, 0.12)",
        "medium": "0 4px 6px rgba(0, 0, 0, 0.1)",
        "large": "0 10px 15px rgba(0, 0, 0, 0.1)"
      }
    },
    "silver-white": {
      "colors": {
        "primary": "#6B7280",
        "secondary": "#9CA3AF",
        "background": "#FFFFFF",
        "surface": "#F9FAFB",
        "text": "#111827",
        "text_secondary": "#6B7280",
        "border": "#E5E7EB",
        "accent": "#3B82F6",
        "success": "#10B981",
        "warning": "#F59E0B",
        "error": "#EF4444"
      },
      "typography": {
        "font_family": "Inter, -apple-system, BlinkMacSystemFont, sans-serif",
        "font_size_base": "16px",
        "font_size_small": "14px",
        "font_size_large": "18px",
        "font_weight_normal": "400",
        "font_weight_bold": "600"
      },
      "spacing": {
        "xs": "4px",
        "sm": "8px",
        "md": "16px",
        "lg": "24px",
        "xl": "32px",
        "xxl": "48px"
      },
      "border_radius": {
        "small": "4px",
        "medium": "8px",
        "large": "12px",
        "round": "50%"
      },
      "shadows": {
        "small": "0 1px 3px rgba(0, 0, 0, 0.1)",
        "medium": "0 4px 6px rgba(0, 0, 0, 0.05)",
        "large": "0 10px 15px rgba(0, 0, 0, 0.1)"
      }
    },
    "minimal": {
      "colors": {
        "primary": "#000000",
        "secondary": "#666666",
        "background": "#FFFFFF",
        "surface": "#FFFFFF",
        "text": "#000000",
        "text_secondary": "#666666",
        "border": "#E0E0E0",
        "accent": "#007AFF",
        "success": "#34C759",
        "warning": "#FF9500",
        "error": "#FF3B30"
      },
      "typography": {
        "font_family": "SF Pro Display, -apple-system, BlinkMacSystemFont, sans-serif",
        "font_size_base": "16px",
        "font_size_small": "14px",
        "font_size_large": "18px",
        "font_weight_normal": "400",
        "font_weight_bold": "600"
      },
      "spacing": {
        "xs": "4px",
        "sm": "8px",
        "md": "16px",
        "lg": "24px",
        "xl": "32px",
        "xxl": "48px"
      },
      "border_radius": {
        "small": "2px",
        "medium": "4px",
        "large": "8px",
        "round": "50%"
      },
      "shadows": {
        "small": "0 1px 2px rgba(0, 0, 0, 0.05)",
        "medium": "0 2px 4px rgba(0, 0, 0, 0.05)",
        "large": "0 4px 8px rgba(0, 0, 0, 0.1)"
      }
    }
  },
  "components": {
    "button": {
      "height": "44px",
      "padding": "0 16px",
      "border_radius": "8px",
      "font_weight": "500",
      "transition": "all 0.2s ease"
    },
    "card": {
      "padding": "16px",
      "border_radius": "8px",
      "shadow": "medium",
      "background": "surface"
    },
    "input": {
      "height": "44px",
      "padding": "0 16px",
      "border_radius": "8px",
      "border": "1px solid",
      "background": "surface"
    },
    "topbar": {
      "height": "44px",
      "padding": "0 16px",
      "background": "surface",
      "border_bottom": "1px solid"
    },
    "tabbar": {
      "height": "60px",
      "background": "surface",
      "border_top": "1px solid",
      "position": "fixed",
      "bottom": "0"
    }
  }
}

3.2 主题配置解析器

class ThemeParser:
    """主题配置解析器"""
    
    def __init__(self, theme_system: ThemeSystem):
        """初始化解析器"""
        self.theme_system = theme_system
    
    def parse_theme_colors(self, theme_name: str) -> Dict[str, str]:
        """解析主题颜色"""
        theme = self.theme_system.get_theme(theme_name)
        colors = theme.get("colors", {})
        
        # 转换为CSS变量格式
        css_variables = {}
        for color_name, color_value in colors.items():
            css_variables[f"--{color_name.replace('_', '-')}"] = color_value
        
        return css_variables
    
    def parse_typography(self, theme_name: str) -> Dict[str, str]:
        """解析字体配置"""
        theme = self.theme_system.get_theme(theme_name)
        typography = theme.get("typography", {})
        
        css_variables = {}
        for prop_name, prop_value in typography.items():
            css_variables[f"--font-{prop_name.replace('_', '-')}"] = prop_value
        
        return css_variables
    
    def parse_spacing(self, theme_name: str) -> Dict[str, str]:
        """解析间距配置"""
        theme = self.theme_system.get_theme(theme_name)
        spacing = theme.get("spacing", {})
        
        css_variables = {}
        for size_name, size_value in spacing.items():
            css_variables[f"--spacing-{size_name}"] = size_value
        
        return css_variables
    
    def parse_border_radius(self, theme_name: str) -> Dict[str, str]:
        """解析圆角配置"""
        theme = self.theme_system.get_theme(theme_name)
        border_radius = theme.get("border_radius", {})
        
        css_variables = {}
        for radius_name, radius_value in border_radius.items():
            css_variables[f"--border-radius-{radius_name}"] = radius_value
        
        return css_variables
    
    def parse_shadows(self, theme_name: str) -> Dict[str, str]:
        """解析阴影配置"""
        theme = self.theme_system.get_theme(theme_name)
        shadows = theme.get("shadows", {})
        
        css_variables = {}
        for shadow_name, shadow_value in shadows.items():
            css_variables[f"--shadow-{shadow_name}"] = shadow_value
        
        return css_variables

4. 三大内置主题详解

4.1 Obsidian Gold主题

4.1.1 设计理念

Obsidian Gold主题采用深色背景配金色点缀的设计风格,营造高端、神秘的视觉体验:

obsidian_gold_theme = {
    "design_concept": "高端神秘",
    "color_scheme": "深色背景 + 金色点缀",
    "target_audience": "高端用户、奢侈品、科技产品",
    "visual_style": "现代、奢华、专业"
}

4.1.2 颜色系统

obsidian_gold_colors = {
    "primary": "#FFD700",      # 主色调:金色
    "secondary": "#B8860B",    # 辅助色:深金色
    "background": "#0E0E0E",   # 背景色:深黑色
    "surface": "#1A1A1A",      # 表面色:深灰色
    "text": "#FFFFFF",         # 主文本:白色
    "text_secondary": "#CCCCCC", # 次要文本:浅灰色
    "border": "#333333",       # 边框色:中灰色
    "accent": "#FF6B35",       # 强调色:橙红色
    "success": "#4CAF50",      # 成功色:绿色
    "warning": "#FF9800",      # 警告色:橙色
    "error": "#F44336"         # 错误色:红色
}

4.1.3 组件样式

def render_obsidian_gold_component(component_type: str, props: Dict) -> str:
    """渲染Obsidian Gold主题组件"""
    if component_type == "button":
        return f"""
        .button {{
            background-color: var(--primary-color);
            color: var(--background-color);
            border: 1px solid var(--primary-color);
            box-shadow: 0 2px 4px rgba(255, 215, 0, 0.3);
        }}
        
        .button:hover {{
            background-color: var(--secondary-color);
            box-shadow: 0 4px 8px rgba(255, 215, 0, 0.4);
        }}"""
    
    elif component_type == "card":
        return f"""
        .card {{
            background-color: var(--surface-color);
            border: 1px solid var(--border-color);
            box-shadow: var(--shadow-medium);
        }}
        
        .card:hover {{
            border-color: var(--primary-color);
            box-shadow: 0 4px 12px rgba(255, 215, 0, 0.2);
        }}"""

4.2 Silver White主题

4.2.1 设计理念

Silver White主题采用简洁的银白色调,体现现代、专业、可信赖的设计风格:

silver_white_theme = {
    "design_concept": "现代专业",
    "color_scheme": "银白色调 + 蓝色点缀",
    "target_audience": "企业用户、商务应用、专业服务",
    "visual_style": "简洁、专业、可信赖"
}

4.2.2 颜色系统

silver_white_colors = {
    "primary": "#6B7280",      # 主色调:银灰色
    "secondary": "#9CA3AF",    # 辅助色:浅灰色
    "background": "#FFFFFF",   # 背景色:纯白色
    "surface": "#F9FAFB",      # 表面色:浅灰色
    "text": "#111827",         # 主文本:深灰色
    "text_secondary": "#6B7280", # 次要文本:中灰色
    "border": "#E5E7EB",       # 边框色:浅灰色
    "accent": "#3B82F6",       # 强调色:蓝色
    "success": "#10B981",      # 成功色:绿色
    "warning": "#F59E0B",      # 警告色:橙色
    "error": "#EF4444"         # 错误色:红色
}

4.2.3 组件样式

def render_silver_white_component(component_type: str, props: Dict) -> str:
    """渲染Silver White主题组件"""
    if component_type == "button":
        return f"""
        .button {{
            background-color: var(--primary-color);
            color: var(--background-color);
            border: 1px solid var(--primary-color);
            box-shadow: 0 1px 3px rgba(107, 114, 128, 0.1);
        }}
        
        .button:hover {{
            background-color: var(--secondary-color);
            box-shadow: 0 2px 4px rgba(107, 114, 128, 0.15);
        }}"""
    
    elif component_type == "card":
        return f"""
        .card {{
            background-color: var(--surface-color);
            border: 1px solid var(--border-color);
            box-shadow: var(--shadow-small);
        }}
        
        .card:hover {{
            border-color: var(--accent-color);
            box-shadow: var(--shadow-medium);
        }}"""

4.3 Minimal主题

4.3.1 设计理念

Minimal主题采用极简的黑白设计,追求简洁、清晰、高效的视觉体验:

minimal_theme = {
    "design_concept": "极简主义",
    "color_scheme": "黑白配色 + 蓝色点缀",
    "target_audience": "追求简洁的用户、内容应用、工具类应用",
    "visual_style": "极简、清晰、高效"
}

4.3.2 颜色系统

minimal_colors = {
    "primary": "#000000",      # 主色调:纯黑色
    "secondary": "#666666",    # 辅助色:中灰色
    "background": "#FFFFFF",   # 背景色:纯白色
    "surface": "#FFFFFF",      # 表面色:纯白色
    "text": "#000000",         # 主文本:纯黑色
    "text_secondary": "#666666", # 次要文本:中灰色
    "border": "#E0E0E0",       # 边框色:浅灰色
    "accent": "#007AFF",       # 强调色:蓝色
    "success": "#34C759",      # 成功色:绿色
    "warning": "#FF9500",      # 警告色:橙色
    "error": "#FF3B30"         # 错误色:红色
}

4.3.3 组件样式

def render_minimal_component(component_type: str, props: Dict) -> str:
    """渲染Minimal主题组件"""
    if component_type == "button":
        return f"""
        .button {{
            background-color: var(--primary-color);
            color: var(--background-color);
            border: 1px solid var(--primary-color);
            box-shadow: none;
        }}
        
        .button:hover {{
            background-color: var(--secondary-color);
            border-color: var(--secondary-color);
        }}"""
    
    elif component_type == "card":
        return f"""
        .card {{
            background-color: var(--surface-color);
            border: 1px solid var(--border-color);
            box-shadow: none;
        }}
        
        .card:hover {{
            border-color: var(--primary-color);
        }}"""

5. 主题应用机制

5.1 主题选择器

class ThemeSelector:
    """主题选择器"""
    
    def __init__(self, theme_system: ThemeSystem):
        """初始化主题选择器"""
        self.theme_system = theme_system
        self.available_themes = list(theme_system.themes.keys())
        self.current_theme = "obsidian-gold"
    
    def select_theme(self, theme_name: str) -> bool:
        """选择主题"""
        if theme_name in self.available_themes:
            self.current_theme = theme_name
            return True
        return False
    
    def get_current_theme(self) -> str:
        """获取当前主题"""
        return self.current_theme
    
    def get_theme_preview(self, theme_name: str) -> Dict:
        """获取主题预览"""
        theme = self.theme_system.get_theme(theme_name)
        return {
            "name": theme_name,
            "colors": theme.get("colors", {}),
            "preview_image": f"/static/themes/{theme_name}_preview.png"
        }

5.2 主题渲染器

class ThemeRenderer:
    """主题渲染器"""
    
    def __init__(self, theme_system: ThemeSystem):
        """初始化主题渲染器"""
        self.theme_system = theme_system
        self.parser = ThemeParser(theme_system)
    
    def render_theme_css(self, theme_name: str) -> str:
        """渲染主题CSS"""
        theme = self.theme_system.get_theme(theme_name)
        
        # 解析各种配置
        colors = self.parser.parse_theme_colors(theme_name)
        typography = self.parser.parse_typography(theme_name)
        spacing = self.parser.parse_spacing(theme_name)
        border_radius = self.parser.parse_border_radius(theme_name)
        shadows = self.parser.parse_shadows(theme_name)
        
        # 生成CSS变量
        css_variables = []
        css_variables.extend([f"  {var}: {value};" for var, value in colors.items()])
        css_variables.extend([f"  {var}: {value};" for var, value in typography.items()])
        css_variables.extend([f"  {var}: {value};" for var, value in spacing.items()])
        css_variables.extend([f"  {var}: {value};" for var, value in border_radius.items()])
        css_variables.extend([f"  {var}: {value};" for var, value in shadows.items()])
        
        css_variables_str = "\n".join(css_variables)
        
        return f"""
.theme-{theme_name} {{
{css_variables_str}
}}"""
    
    def render_component_styles(self, theme_name: str, component_type: str) -> str:
        """渲染组件样式"""
        theme = self.theme_system.get_theme(theme_name)
        component_config = self.theme_system.get_component_config(component_type)
        
        # 根据组件类型生成样式
        if component_type == "button":
            return self._render_button_styles(theme, component_config)
        elif component_type == "card":
            return self._render_card_styles(theme, component_config)
        elif component_type == "input":
            return self._render_input_styles(theme, component_config)
        # ... 其他组件类型
    
    def _render_button_styles(self, theme: Dict, config: Dict) -> str:
        """渲染按钮样式"""
        return f"""
.theme-{theme.get('name', 'default')} .button {{
    height: {config.get('height', '44px')};
    padding: {config.get('padding', '0 16px')};
    border-radius: {config.get('border_radius', '8px')};
    font-weight: {config.get('font_weight', '500')};
    transition: {config.get('transition', 'all 0.2s ease')};
    background-color: var(--primary-color);
    color: var(--background-color);
    border: 1px solid var(--primary-color);
}}

.theme-{theme.get('name', 'default')} .button:hover {{
    background-color: var(--secondary-color);
    border-color: var(--secondary-color);
}}"""

6. 主题切换系统

6.1 动态主题切换

class DynamicThemeSwitcher:
    """动态主题切换器"""
    
    def __init__(self, theme_system: ThemeSystem):
        """初始化动态主题切换器"""
        self.theme_system = theme_system
        self.current_theme = "obsidian-gold"
        self.theme_cache = {}
    
    def switch_theme(self, theme_name: str) -> bool:
        """切换主题"""
        if theme_name not in self.theme_system.themes:
            return False
        
        # 缓存当前主题
        self.theme_cache[self.current_theme] = self._get_current_theme_state()
        
        # 切换到新主题
        self.current_theme = theme_name
        self._apply_theme(theme_name)
        
        return True
    
    def _get_current_theme_state(self) -> Dict:
        """获取当前主题状态"""
        # 获取当前页面的主题状态
        return {
            "theme_name": self.current_theme,
            "applied_at": time.time()
        }
    
    def _apply_theme(self, theme_name: str) -> None:
        """应用主题"""
        # 生成主题CSS
        theme_css = self._generate_theme_css(theme_name)
        
        # 应用到页面
        self._inject_theme_css(theme_css)
        
        # 触发主题切换事件
        self._trigger_theme_change_event(theme_name)
    
    def _generate_theme_css(self, theme_name: str) -> str:
        """生成主题CSS"""
        renderer = ThemeRenderer(self.theme_system)
        return renderer.render_theme_css(theme_name)
    
    def _inject_theme_css(self, css: str) -> None:
        """注入主题CSS"""
        # 移除旧的主题样式
        self._remove_old_theme_styles()
        
        # 注入新的主题样式
        style_element = f"<style id='dynamic-theme'>{css}</style>"
        # 这里需要根据具体的渲染环境来实现CSS注入
    
    def _remove_old_theme_styles(self) -> None:
        """移除旧的主题样式"""
        # 移除旧的主题样式元素
        pass
    
    def _trigger_theme_change_event(self, theme_name: str) -> None:
        """触发主题切换事件"""
        # 触发主题切换事件,通知其他组件
        pass

6.2 主题持久化

class ThemePersistence:
    """主题持久化"""
    
    def __init__(self, storage_key: str = "selected_theme"):
        """初始化主题持久化"""
        self.storage_key = storage_key
    
    def save_theme(self, theme_name: str) -> None:
        """保存主题选择"""
        # 保存到本地存储
        if hasattr(self, '_save_to_local_storage'):
            self._save_to_local_storage(theme_name)
        
        # 保存到服务器
        if hasattr(self, '_save_to_server'):
            self._save_to_server(theme_name)
    
    def load_theme(self) -> str:
        """加载主题选择"""
        # 从本地存储加载
        if hasattr(self, '_load_from_local_storage'):
            theme = self._load_from_local_storage()
            if theme:
                return theme
        
        # 从服务器加载
        if hasattr(self, '_load_from_server'):
            theme = self._load_from_server()
            if theme:
                return theme
        
        # 返回默认主题
        return "obsidian-gold"
    
    def _save_to_local_storage(self, theme_name: str) -> None:
        """保存到本地存储"""
        # 实现本地存储逻辑
        pass
    
    def _load_from_local_storage(self) -> str:
        """从本地存储加载"""
        # 实现本地存储加载逻辑
        return None
    
    def _save_to_server(self, theme_name: str) -> None:
        """保存到服务器"""
        # 实现服务器保存逻辑
        pass
    
    def _load_from_server(self) -> str:
        """从服务器加载"""
        # 实现服务器加载逻辑
        return None

7. 自定义主题开发

7.1 主题开发指南

class CustomThemeBuilder:
    """自定义主题构建器"""
    
    def __init__(self, theme_system: ThemeSystem):
        """初始化自定义主题构建器"""
        self.theme_system = theme_system
        self.theme_template = self._load_theme_template()
    
    def _load_theme_template(self) -> Dict:
        """加载主题模板"""
        return {
            "colors": {
                "primary": "#000000",
                "secondary": "#000000",
                "background": "#FFFFFF",
                "surface": "#FFFFFF",
                "text": "#000000",
                "text_secondary": "#000000",
                "border": "#000000",
                "accent": "#000000",
                "success": "#000000",
                "warning": "#000000",
                "error": "#000000"
            },
            "typography": {
                "font_family": "Arial, sans-serif",
                "font_size_base": "16px",
                "font_size_small": "14px",
                "font_size_large": "18px",
                "font_weight_normal": "400",
                "font_weight_bold": "600"
            },
            "spacing": {
                "xs": "4px",
                "sm": "8px",
                "md": "16px",
                "lg": "24px",
                "xl": "32px",
                "xxl": "48px"
            },
            "border_radius": {
                "small": "4px",
                "medium": "8px",
                "large": "12px",
                "round": "50%"
            },
            "shadows": {
                "small": "0 1px 3px rgba(0, 0, 0, 0.12)",
                "medium": "0 4px 6px rgba(0, 0, 0, 0.1)",
                "large": "0 10px 15px rgba(0, 0, 0, 0.1)"
            }
        }
    
    def create_theme(self, theme_name: str, theme_config: Dict) -> bool:
        """创建自定义主题"""
        # 验证主题配置
        if not self._validate_theme_config(theme_config):
            return False
        
        # 合并主题配置
        full_theme_config = self._merge_theme_config(theme_config)
        
        # 保存主题配置
        self._save_theme_config(theme_name, full_theme_config)
        
        return True
    
    def _validate_theme_config(self, config: Dict) -> bool:
        """验证主题配置"""
        required_sections = ["colors", "typography", "spacing", "border_radius", "shadows"]
        
        for section in required_sections:
            if section not in config:
                return False
        
        # 验证颜色配置
        required_colors = ["primary", "secondary", "background", "surface", "text", "text_secondary", "border", "accent", "success", "warning", "error"]
        for color in required_colors:
            if color not in config["colors"]:
                return False
        
        return True
    
    def _merge_theme_config(self, config: Dict) -> Dict:
        """合并主题配置"""
        merged_config = self.theme_template.copy()
        
        for section, values in config.items():
            if section in merged_config:
                merged_config[section].update(values)
        
        return merged_config
    
    def _save_theme_config(self, theme_name: str, config: Dict) -> None:
        """保存主题配置"""
        # 加载现有配置
        with open(self.theme_system.tokens_path, 'r', encoding='utf-8') as f:
            tokens = json.load(f)
        
        # 添加新主题
        tokens["themes"][theme_name] = config
        
        # 保存配置
        with open(self.theme_system.tokens_path, 'w', encoding='utf-8') as f:
            json.dump(tokens, f, indent=2, ensure_ascii=False)

7.2 主题预览系统

class ThemePreviewGenerator:
    """主题预览生成器"""
    
    def __init__(self, theme_system: ThemeSystem):
        """初始化主题预览生成器"""
        self.theme_system = theme_system
        self.preview_components = [
            "button", "card", "input", "topbar", "tabbar"
        ]
    
    def generate_theme_preview(self, theme_name: str) -> str:
        """生成主题预览"""
        theme = self.theme_system.get_theme(theme_name)
        renderer = ThemeRenderer(self.theme_system)
        
        # 生成主题CSS
        theme_css = renderer.render_theme_css(theme_name)
        
        # 生成预览HTML
        preview_html = self._generate_preview_html(theme_name, theme_css)
        
        return preview_html
    
    def _generate_preview_html(self, theme_name: str, theme_css: str) -> str:
        """生成预览HTML"""
        return f"""
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{theme_name} 主题预览</title>
    <style>
        {theme_css}
        
        .preview-container {{
            padding: 20px;
            background-color: var(--background-color);
            color: var(--text-color);
            font-family: var(--font-family);
        }}
        
        .preview-section {{
            margin-bottom: 30px;
        }}
        
        .preview-title {{
            font-size: 18px;
            font-weight: 600;
            margin-bottom: 15px;
            color: var(--text-color);
        }}
        
        .preview-grid {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
        }}
        
        .preview-item {{
            padding: 15px;
            background-color: var(--surface-color);
            border: 1px solid var(--border-color);
            border-radius: var(--border-radius-medium);
        }}
        
        .preview-item h3 {{
            margin: 0 0 10px 0;
            font-size: 14px;
            color: var(--text-secondary-color);
        }}
        
        .button {{
            height: 44px;
            padding: 0 16px;
            border-radius: 8px;
            font-weight: 500;
            border: none;
            cursor: pointer;
            background-color: var(--primary-color);
            color: var(--background-color);
        }}
        
        .button:hover {{
            background-color: var(--secondary-color);
        }}
        
        .card {{
            padding: 16px;
            border-radius: 8px;
            background-color: var(--surface-color);
            border: 1px solid var(--border-color);
        }}
        
        .input {{
            height: 44px;
            padding: 0 16px;
            border-radius: 8px;
            border: 1px solid var(--border-color);
            background-color: var(--surface-color);
            color: var(--text-color);
        }}
        
        .topbar {{
            height: 44px;
            padding: 0 16px;
            background-color: var(--surface-color);
            border-bottom: 1px solid var(--border-color);
            display: flex;
            align-items: center;
            justify-content: space-between;
        }}
        
        .tabbar {{
            height: 60px;
            background-color: var(--surface-color);
            border-top: 1px solid var(--border-color);
            display: flex;
            align-items: center;
            justify-content: space-around;
        }}
    </style>
</head>
<body class="theme-{theme_name}">
    <div class="preview-container">
        <h1>{theme_name} 主题预览</h1>
        
        <div class="preview-section">
            <h2 class="preview-title">按钮组件</h2>
            <div class="preview-grid">
                <div class="preview-item">
                    <h3>主要按钮</h3>
                    <button class="button">主要按钮</button>
                </div>
                <div class="preview-item">
                    <h3>次要按钮</h3>
                    <button class="button" style="background-color: var(--secondary-color);">次要按钮</button>
                </div>
            </div>
        </div>
        
        <div class="preview-section">
            <h2 class="preview-title">卡片组件</h2>
            <div class="preview-grid">
                <div class="preview-item">
                    <h3>基础卡片</h3>
                    <div class="card">
                        <h4>卡片标题</h4>
                        <p>这是卡片内容,展示主题的视觉效果。</p>
                    </div>
                </div>
            </div>
        </div>
        
        <div class="preview-section">
            <h2 class="preview-title">输入框组件</h2>
            <div class="preview-grid">
                <div class="preview-item">
                    <h3>文本输入</h3>
                    <input type="text" class="input" placeholder="请输入内容">
                </div>
            </div>
        </div>
        
        <div class="preview-section">
            <h2 class="preview-title">导航组件</h2>
            <div class="preview-grid">
                <div class="preview-item">
                    <h3>顶部栏</h3>
                    <div class="topbar">
                        <span>标题</span>
                        <span>操作</span>
                    </div>
                </div>
                <div class="preview-item">
                    <h3>底部导航</h3>
                    <div class="tabbar">
                        <span>首页</span>
                        <span>分类</span>
                        <span>购物车</span>
                        <span>我的</span>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>
"""

8. 主题系统集成

8.1 渲染引擎集成

class ThemeIntegratedRenderer:
    """主题集成渲染器"""
    
    def __init__(self, theme_system: ThemeSystem):
        """初始化主题集成渲染器"""
        self.theme_system = theme_system
        self.theme_renderer = ThemeRenderer(theme_system)
    
    def render_with_theme(self, dsl: Dict, theme_name: str) -> Dict[str, str]:
        """使用指定主题渲染UI"""
        # 获取主题配置
        theme = self.theme_system.get_theme(theme_name)
        
        # 渲染PNG图片
        png_renderer = UIRenderer()
        png_renderer.set_theme(theme)
        png_image = png_renderer.render(dsl)
        
        # 渲染Vue页面
        vue_renderer = VueRenderer()
        vue_renderer.set_theme(theme)
        vue_page = vue_renderer.render(dsl)
        
        return {
            "theme": theme_name,
            "png": png_image,
            "vue": vue_page
        }
    
    def render_all_themes(self, dsl: Dict) -> Dict[str, Dict[str, str]]:
        """使用所有主题渲染UI"""
        results = {}
        
        for theme_name in self.theme_system.themes.keys():
            results[theme_name] = self.render_with_theme(dsl, theme_name)
        
        return results

8.2 API集成

# 在FastAPI中集成主题系统
@app.get("/themes")
async def get_available_themes():
    """获取可用主题列表"""
    theme_system = ThemeSystem()
    themes = []
    
    for theme_name in theme_system.themes.keys():
        theme = theme_system.get_theme(theme_name)
        themes.append({
            "name": theme_name,
            "display_name": theme.get("display_name", theme_name),
            "description": theme.get("description", ""),
            "preview_url": f"/themes/{theme_name}/preview"
        })
    
    return {"themes": themes}

@app.get("/themes/{theme_name}/preview")
async def get_theme_preview(theme_name: str):
    """获取主题预览"""
    theme_system = ThemeSystem()
    
    if theme_name not in theme_system.themes:
        raise HTTPException(status_code=404, detail="主题不存在")
    
    preview_generator = ThemePreviewGenerator(theme_system)
    preview_html = preview_generator.generate_theme_preview(theme_name)
    
    return HTMLResponse(content=preview_html)

@app.post("/themes/{theme_name}/apply")
async def apply_theme(theme_name: str, dsl: Dict):
    """应用主题到UI设计"""
    theme_system = ThemeSystem()
    
    if theme_name not in theme_system.themes:
        raise HTTPException(status_code=404, detail="主题不存在")
    
    integrated_renderer = ThemeIntegratedRenderer(theme_system)
    result = integrated_renderer.render_with_theme(dsl, theme_name)
    
    return result

9. 主题系统最佳实践

9.1 主题设计原则

theme_design_principles = {
    "color_contrast": {
        "description": "确保足够的颜色对比度",
        "min_contrast_ratio": 4.5,
        "recommended_ratio": 7.0
    },
    "accessibility": {
        "description": "支持无障碍访问",
        "color_blind_support": True,
        "high_contrast_mode": True
    },
    "consistency": {
        "description": "保持视觉一致性",
        "color_harmony": True,
        "spacing_consistency": True
    },
    "performance": {
        "description": "优化性能",
        "css_optimization": True,
        "lazy_loading": True
    }
}

9.2 主题测试策略

class ThemeTester:
    """主题测试器"""
    
    def __init__(self, theme_system: ThemeSystem):
        """初始化主题测试器"""
        self.theme_system = theme_system
    
    def test_theme_accessibility(self, theme_name: str) -> Dict[str, bool]:
        """测试主题无障碍性"""
        theme = self.theme_system.get_theme(theme_name)
        colors = theme.get("colors", {})
        
        results = {
            "color_contrast": self._test_color_contrast(colors),
            "color_blind_support": self._test_color_blind_support(colors),
            "text_readability": self._test_text_readability(colors)
        }
        
        return results
    
    def _test_color_contrast(self, colors: Dict) -> bool:
        """测试颜色对比度"""
        # 实现颜色对比度测试
        return True
    
    def _test_color_blind_support(self, colors: Dict) -> bool:
        """测试色盲支持"""
        # 实现色盲支持测试
        return True
    
    def _test_text_readability(self, colors: Dict) -> bool:
        """测试文本可读性"""
        # 实现文本可读性测试
        return True
    
    def test_theme_consistency(self, theme_name: str) -> Dict[str, bool]:
        """测试主题一致性"""
        theme = self.theme_system.get_theme(theme_name)
        
        results = {
            "color_harmony": self._test_color_harmony(theme),
            "spacing_consistency": self._test_spacing_consistency(theme),
            "typography_consistency": self._test_typography_consistency(theme)
        }
        
        return results
    
    def _test_color_harmony(self, theme: Dict) -> bool:
        """测试颜色和谐性"""
        # 实现颜色和谐性测试
        return True
    
    def _test_spacing_consistency(self, theme: Dict) -> bool:
        """测试间距一致性"""
        # 实现间距一致性测试
        return True
    
    def _test_typography_consistency(self, theme: Dict) -> bool:
        """测试字体一致性"""
        # 实现字体一致性测试
        return True

通过掌握这些多主题支持技术,您可以构建一个灵活、可扩展、用户友好的主题系统。主题系统是UI生成系统的重要组成部分,需要精心设计和持续优化,以提供最佳的用户体验。

Prev
Vue页面渲染系统
Next
FastAPI服务设计