高级示例¶
本页面展示 EmailWidget 的高级功能和自定义扩展,包括自定义组件、主题系统、性能优化等深入应用。
自定义组件开发¶
创建自定义 Widget 组件¶
Python
from email_widget.core.base import BaseWidget
from email_widget.core.enums import TextAlign
from email_widget.core.config import EmailConfig
from email_widget import Email
class MetricCardWidget(BaseWidget):
"""自定义指标卡片组件"""
def __init__(self):
super().__init__()
self._title = ""
self._value = ""
self._change = 0.0
self._change_label = ""
self._icon = "📊"
self._color_scheme = "primary"
def set_title(self, title: str) -> 'MetricCardWidget':
"""设置卡片标题"""
self._title = title
return self
def set_value(self, value: str) -> 'MetricCardWidget':
"""设置主要数值"""
self._value = value
return self
def set_change(self, change: float, label: str = "") -> 'MetricCardWidget':
"""设置变化值和标签"""
self._change = change
self._change_label = label or f"{change:+.1f}%"
return self
def set_icon(self, icon: str) -> 'MetricCardWidget':
"""设置图标"""
self._icon = icon
return self
def set_color_scheme(self, scheme: str) -> 'MetricCardWidget':
"""设置颜色方案: primary, success, warning, danger"""
self._color_scheme = scheme
return self
def _get_color_styles(self) -> dict:
"""获取颜色样式"""
schemes = {
'primary': {'bg': '#3498db', 'text': '#ffffff', 'accent': '#2980b9'},
'success': {'bg': '#2ecc71', 'text': '#ffffff', 'accent': '#27ae60'},
'warning': {'bg': '#f39c12', 'text': '#ffffff', 'accent': '#e67e22'},
'danger': {'bg': '#e74c3c', 'text': '#ffffff', 'accent': '#c0392b'}
}
return schemes.get(self._color_scheme, schemes['primary'])
def render(self) -> str:
"""渲染组件HTML"""
colors = self._get_color_styles()
# 变化指标的颜色
change_color = "#27ae60" if self._change >= 0 else "#e74c3c"
change_arrow = "↗" if self._change >= 0 else "↘"
return f"""
<div style="
background: linear-gradient(135deg, {colors['bg']}, {colors['accent']});
color: {colors['text']};
padding: 20px;
margin: 10px 0;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
">
<div style="display: flex; align-items: center; margin-bottom: 15px;">
<span style="font-size: 24px; margin-right: 10px;">{self._icon}</span>
<h3 style="margin: 0; font-size: 16px; font-weight: 600; opacity: 0.9;">
{self._title}
</h3>
</div>
<div style="font-size: 32px; font-weight: 700; margin-bottom: 8px;">
{self._value}
</div>
<div style="display: flex; align-items: center; font-size: 14px;">
<span style="color: {change_color}; font-weight: 600; margin-right: 5px;">
{change_arrow} {self._change_label}
</span>
<span style="opacity: 0.8;">较上期</span>
</div>
</div>
"""
# 使用自定义组件
email = Email("自定义组件演示")
email.add_title("🛠️ 自定义 MetricCard 组件演示", TextType.TITLE_LARGE)
# 创建多个指标卡片
metrics = [
("月度收入", "¥1,250,000", 15.8, "primary", "💰"),
("新增用户", "2,847", 23.5, "success", "👥"),
("转化率", "3.2%", -2.1, "warning", "📈"),
("退款率", "1.8%", -5.4, "success", "✅")
]
for title, value, change, scheme, icon in metrics:
metric_card = MetricCardWidget()
metric_card.set_title(title) \
.set_value(value) \
.set_change(change) \
.set_color_scheme(scheme) \
.set_icon(icon)
email.add_widget(metric_card)
email.export_html("custom_components_demo.html")
print("✅ 自定义组件演示已生成:custom_components_demo.html")
商务主题演示
🎨 商务主题演示
9. 信息提示
Widget渲染错误: ThemedWidget (themedwidget_ef0d790f)
错误详情: 模板未定义
错误详情: 模板未定义
10. 成功消息
Widget渲染错误: ThemedWidget (themedwidget_564ee5a7)
错误详情: 模板未定义
错误详情: 模板未定义
11. 警告信息
Widget渲染错误: ThemedWidget (themedwidget_6a7d1977)
错误详情: 模板未定义
错误详情: 模板未定义
12. 错误提示
Widget渲染错误: ThemedWidget (themedwidget_c1a12efa)
错误详情: 模板未定义
错误详情: 模板未定义
|
自定义组件特点: - 继承 BaseWidget 基类 - 支持链式调用 - 自定义样式和布局 - 可复用的业务组件
主题系统扩展¶
自定义主题和样式¶
Python
from email_widget import Email, TextWidget, TableWidget
from email_widget.core.config import EmailConfig
from email_widget.core.enums import TextType
class DarkThemeConfig(EmailConfig):
"""深色主题配置"""
@classmethod
def get_primary_color(cls) -> str:
return "#1a1a1a"
@classmethod
def get_background_color(cls) -> str:
return "#2d2d2d"
@classmethod
def get_text_color(cls) -> str:
return "#ffffff"
@classmethod
def get_accent_color(cls) -> str:
return "#64ffda"
@classmethod
def get_border_color(cls) -> str:
return "#404040"
class BusinessThemeConfig(EmailConfig):
"""商务主题配置"""
@classmethod
def get_primary_color(cls) -> str:
return "#2c3e50"
@classmethod
def get_secondary_color(cls) -> str:
return "#34495e"
@classmethod
def get_accent_color(cls) -> str:
return "#3498db"
@classmethod
def get_success_color(cls) -> str:
return "#27ae60"
class ThemedWidget(BaseWidget):
"""支持主题的自定义组件"""
def __init__(self, theme_config=None):
super().__init__()
self._theme_config = theme_config or EmailConfig
self._content = ""
self._widget_type = "info"
def set_content(self, content: str) -> 'ThemedWidget':
self._content = content
return self
def set_type(self, widget_type: str) -> 'ThemedWidget':
"""设置组件类型: info, success, warning, danger"""
self._widget_type = widget_type
return self
def render(self) -> str:
# 根据主题配置获取颜色
theme_colors = {
'info': self._theme_config.get_primary_color(),
'success': self._theme_config.get_success_color(),
'warning': getattr(self._theme_config, 'get_warning_color', lambda: '#f39c12')(),
'danger': getattr(self._theme_config, 'get_danger_color', lambda: '#e74c3c')()
}
bg_color = self._theme_config.get_background_color()
text_color = self._theme_config.get_text_color()
border_color = theme_colors.get(self._widget_type, self._theme_config.get_primary_color())
return f"""
<div style="
background-color: {bg_color};
color: {text_color};
border-left: 4px solid {border_color};
padding: 15px;
margin: 10px 0;
border-radius: 4px;
font-family: Arial, sans-serif;
">
{self._content}
</div>
"""
# 主题演示
def create_themed_report(theme_config, theme_name):
"""创建指定主题的报告"""
email = Email(f"{theme_name}主题演示")
# 设置邮件的主题配置
email._config = theme_config
email.add_title(f"🎨 {theme_name}主题演示", TextType.TITLE_LARGE)
# 使用主题化组件
themed_widgets = [
("信息提示", "这是一个信息类型的提示框", "info"),
("成功消息", "操作已成功完成", "success"),
("警告信息", "请注意检查相关设置", "warning"),
("错误提示", "发生了一个错误,请重试", "danger")
]
for title, content, widget_type in themed_widgets:
email.add_text(title, type=TextType.SECTION_H3)
themed_widget = ThemedWidget(theme_config)
themed_widget.set_content(content).set_type(widget_type)
email.add_widget(themed_widget)
# 创建主题化表格
table = TableWidget()
table.set_headers(["功能", "状态", "备注"])
table.add_row(["用户登录", "✅ 正常", "登录成功率 98.5%"])
table.add_row(["数据同步", "🔄 处理中", "预计5分钟完成"])
table.add_row(["邮件发送", "❌ 异常", "SMTP服务器连接失败"])
# 应用主题样式到表格
table._theme_config = theme_config
email.add_widget(table)
return email
# 创建不同主题的报告
themes = [
(EmailConfig, "默认"),
(DarkThemeConfig, "深色"),
(BusinessThemeConfig, "商务")
]
for theme_config, theme_name in themes:
email = create_themed_report(theme_config, theme_name)
email.export_html(f"{theme_name.lower()}_theme_demo.html")
print(f"✅ {theme_name}主题演示已生成")
默认主题演示
🎨 默认主题演示
1. 信息提示
Widget渲染错误: ThemedWidget (themedwidget_99cccf68)
错误详情: 模板未定义
错误详情: 模板未定义
2. 成功消息
Widget渲染错误: ThemedWidget (themedwidget_d663b636)
错误详情: 模板未定义
错误详情: 模板未定义
3. 警告信息
Widget渲染错误: ThemedWidget (themedwidget_29e78c10)
错误详情: 模板未定义
错误详情: 模板未定义
4. 错误提示
Widget渲染错误: ThemedWidget (themedwidget_9047de7b)
错误详情: 模板未定义
错误详情: 模板未定义
|
深色主题演示
🎨 深色主题演示
5. 信息提示
Widget渲染错误: ThemedWidget (themedwidget_df9fc062)
错误详情: 模板未定义
错误详情: 模板未定义
6. 成功消息
Widget渲染错误: ThemedWidget (themedwidget_c1d279ce)
错误详情: 模板未定义
错误详情: 模板未定义
7. 警告信息
Widget渲染错误: ThemedWidget (themedwidget_a55e10b1)
错误详情: 模板未定义
错误详情: 模板未定义
8. 错误提示
Widget渲染错误: ThemedWidget (themedwidget_6477e200)
错误详情: 模板未定义
错误详情: 模板未定义
|
商务主题演示
🎨 商务主题演示
9. 信息提示
Widget渲染错误: ThemedWidget (themedwidget_ef0d790f)
错误详情: 模板未定义
错误详情: 模板未定义
10. 成功消息
Widget渲染错误: ThemedWidget (themedwidget_564ee5a7)
错误详情: 模板未定义
错误详情: 模板未定义
11. 警告信息
Widget渲染错误: ThemedWidget (themedwidget_6a7d1977)
错误详情: 模板未定义
错误详情: 模板未定义
12. 错误提示
Widget渲染错误: ThemedWidget (themedwidget_c1a12efa)
错误详情: 模板未定义
错误详情: 模板未定义
|
Text Only
**主题系统特点:**
- 可扩展的配置系统
- 主题化组件支持
- 一致的视觉风格
- 易于切换和定制
---
## 模板引擎扩展
### 自定义模板和过滤器
```python
from jinja2 import Environment, BaseLoader
from email_widget.core.template_engine import TemplateEngine
from email_widget import Email
import re
class CustomTemplateEngine(TemplateEngine):
"""扩展的模板引擎"""
def __init__(self):
super().__init__()
# 添加自定义过滤器
self._env.filters.update({
'currency': self._currency_filter,
'percentage': self._percentage_filter,
'truncate_smart': self._smart_truncate_filter,
'highlight': self._highlight_filter
})
def _currency_filter(self, value, currency='¥'):
"""货币格式化过滤器"""
try:
num_value = float(value)
return f"{currency}{num_value:,.2f}"
except (ValueError, TypeError):
return str(value)
def _percentage_filter(self, value, decimals=1):
"""百分比格式化过滤器"""
try:
num_value = float(value)
return f"{num_value:.{decimals}f}%"
except (ValueError, TypeError):
return str(value)
def _smart_truncate_filter(self, text, length=50, suffix='...'):
"""智能截断过滤器,在单词边界截断"""
if len(text) <= length:
return text
truncated = text[:length]
# 找到最后一个空格位置
last_space = truncated.rfind(' ')
if last_space > length * 0.7: # 如果空格位置合理
truncated = truncated[:last_space]
return truncated + suffix
def _highlight_filter(self, text, keywords, css_class='highlight'):
"""关键词高亮过滤器"""
if not keywords:
return text
if isinstance(keywords, str):
keywords = [keywords]
highlighted_text = text
for keyword in keywords:
pattern = re.compile(re.escape(keyword), re.IGNORECASE)
highlighted_text = pattern.sub(
f'<span class="{css_class}" style="background-color: #ffeb3b; padding: 2px 4px;">{keyword}</span>',
highlighted_text
)
return highlighted_text
class AdvancedReportWidget(BaseWidget):
"""使用高级模板的报告组件"""
def __init__(self):
super().__init__()
self._template_engine = CustomTemplateEngine()
self._data = {}
self._template_name = "default"
def set_data(self, data: dict) -> 'AdvancedReportWidget':
"""设置模板数据"""
self._data = data
return self
def set_template(self, template_name: str) -> 'AdvancedReportWidget':
"""设置模板名称"""
self._template_name = template_name
return self
def render(self) -> str:
"""使用模板渲染组件"""
# 定义不同的模板
templates = {
'sales_summary': """
<div style="border: 1px solid #ddd; padding: 20px; margin: 10px 0; border-radius: 8px;">
<h3 style="color: #2c3e50; margin-top: 0;">{{ title }}</h3>
<div style="display: flex; flex-wrap: wrap; gap: 15px; margin-bottom: 20px;">
{% for metric in metrics %}
<div style="
background: linear-gradient(135deg, #3498db, #2980b9);
color: white;
padding: 15px;
border-radius: 8px;
min-width: 150px;
text-align: center;
">
<div style="font-size: 24px; font-weight: bold;">
{{ metric.value | currency if metric.type == 'currency' else metric.value }}
</div>
<div style="font-size: 14px; opacity: 0.9;">{{ metric.label }}</div>
{% if metric.change %}
<div style="font-size: 12px; margin-top: 5px;">
<span style="color: {{ '#4caf50' if metric.change > 0 else '#f44336' }};">
{{ metric.change | percentage }}
</span>
</div>
{% endif %}
</div>
{% endfor %}
</div>
{% if description %}
<p style="color: #666; line-height: 1.6;">
{{ description | highlight(keywords) }}
</p>
{% endif %}
</div>
""",
'data_table': """
<div style="margin: 15px 0;">
<h4 style="color: #2c3e50;">{{ title }}</h4>
<table style="width: 100%; border-collapse: collapse; font-size: 14px;">
<thead>
<tr style="background-color: #f8f9fa;">
{% for header in headers %}
<th style="padding: 12px; text-align: left; border-bottom: 2px solid #dee2e6;">
{{ header }}
</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in rows %}
<tr style="{{ 'background-color: #f8f9fa;' if loop.index % 2 == 0 else '' }}">
{% for cell in row %}
<td style="padding: 10px; border-bottom: 1px solid #dee2e6;">
{% if cell.type == 'currency' %}
{{ cell.value | currency }}
{% elif cell.type == 'percentage' %}
{{ cell.value | percentage }}
{% else %}
{{ cell.value }}
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
"""
}
template_content = templates.get(self._template_name, templates['sales_summary'])
return self._template_engine.render_string(template_content, **self._data)
# 使用高级模板组件
email = Email("高级模板演示")
email.add_title("🔧 高级模板引擎演示", TextType.TITLE_LARGE)
# 销售汇总模板示例
sales_data = {
'title': '月度销售业绩汇总',
'metrics': [
{'label': '总销售额', 'value': 1250000, 'type': 'currency', 'change': 15.8},
{'label': '新客户数', 'value': '2,847', 'change': 23.5},
{'label': '客单价', 'value': 438.5, 'type': 'currency', 'change': -2.1},
{'label': '转化率', 'value': 3.2, 'type': 'percentage', 'change': 0.8}
],
'description': '本月销售业绩表现优秀,总销售额创新高。新客户获取效果显著,但需要关注客单价的下降趋势。',
'keywords': ['销售额', '新客户', '客单价']
}
sales_widget = AdvancedReportWidget()
sales_widget.set_template('sales_summary').set_data(sales_data)
email.add_widget(sales_widget)
# 数据表格模板示例
table_data = {
'title': '产品销售明细',
'headers': ['产品名称', '销售数量', '单价', '销售额', '增长率'],
'rows': [
[
{'value': '智能手机A'},
{'value': '1,200'},
{'value': 2999, 'type': 'currency'},
{'value': 3598800, 'type': 'currency'},
{'value': 15.8, 'type': 'percentage'}
],
[
{'value': '平板电脑B'},
{'value': '800'},
{'value': 1999, 'type': 'currency'},
{'value': 1599200, 'type': 'currency'},
{'value': -5.2, 'type': 'percentage'}
]
]
}
table_widget = AdvancedReportWidget()
table_widget.set_template('data_table').set_data(table_data)
email.add_widget(table_widget)
email.export_html("advanced_template_demo.html")
print("✅ 高级模板演示已生成:advanced_template_demo.html")
高级模板演示
🔧 高级模板引擎演示
Widget渲染错误: AdvancedReportWidget (advancedreportwidget_305aa5f1)
错误详情: 模板未定义
错误详情: 模板未定义
Widget渲染错误: AdvancedReportWidget (advancedreportwidget_7637650e)
错误详情: 模板未定义
错误详情: 模板未定义
模板引擎扩展特点: - 自定义 Jinja2 过滤器 - 灵活的模板系统 - 数据驱动的渲染 - 可复用的模板组件
性能优化技巧¶
缓存和批量处理优化¶
Python
from functools import lru_cache
import time
from concurrent.futures import ThreadPoolExecutor
from email_widget import Email
from email_widget.core.cache import Cache
class PerformanceOptimizedEmail(Email):
"""性能优化的邮件类"""
def __init__(self, title: str):
super().__init__(title)
self._cache = Cache(max_size=1000)
self._batch_operations = []
self._lazy_render = True
@lru_cache(maxsize=128)
def _get_cached_template(self, template_name: str) -> str:
"""缓存模板内容"""
# 模拟从文件系统加载模板
time.sleep(0.01) # 模拟I/O延迟
return f"<!-- Cached template: {template_name} -->"
def add_widgets_batch(self, widgets: list, chunk_size: int = 10):
"""批量添加组件,提高性能"""
def process_chunk(chunk):
for widget in chunk:
if hasattr(widget, 'validate'):
widget.validate() # 验证组件
self._widgets.append(widget)
# 分块处理大量组件
chunks = [widgets[i:i + chunk_size] for i in range(0, len(widgets), chunk_size)]
with ThreadPoolExecutor(max_workers=4) as executor:
executor.map(process_chunk, chunks)
def render_async(self) -> str:
"""异步渲染,提高大型报告的性能"""
def render_widget_chunk(widgets_chunk):
return ''.join(widget.render() for widget in widgets_chunk)
# 分块渲染组件
chunk_size = 5
widget_chunks = [self._widgets[i:i + chunk_size]
for i in range(0, len(self._widgets), chunk_size)]
with ThreadPoolExecutor(max_workers=4) as executor:
rendered_chunks = list(executor.map(render_widget_chunk, widget_chunks))
return self._template_engine.render('email_template.html', {
'title': self._title,
'widgets_html': ''.join(rendered_chunks)
})
class LazyLoadWidget(BaseWidget):
"""延迟加载的组件"""
def __init__(self):
super().__init__()
self._data_loader = None
self._cache_key = None
self._rendered_cache = None
def set_data_loader(self, loader_func, cache_key: str = None):
"""设置数据加载函数"""
self._data_loader = loader_func
self._cache_key = cache_key or f"widget_{id(self)}"
return self
def render(self) -> str:
"""延迟渲染,只在需要时加载数据"""
if self._rendered_cache is not None:
return self._rendered_cache
# 检查缓存
if hasattr(self, '_cache') and self._cache_key:
cached_result = self._cache.get(self._cache_key)
if cached_result:
return cached_result
# 加载数据并渲染
if self._data_loader:
data = self._data_loader()
rendered = self._render_with_data(data)
# 缓存结果
if hasattr(self, '_cache') and self._cache_key:
self._cache.set(self._cache_key, rendered)
self._rendered_cache = rendered
return rendered
return "<div><!-- LazyLoadWidget: No data loader --></div>"
def _render_with_data(self, data) -> str:
"""使用数据渲染组件"""
return f"<div>Loaded data: {len(data) if hasattr(data, '__len__') else 'N/A'} items</div>"
# 性能优化演示
def create_large_dataset():
"""模拟创建大数据集"""
time.sleep(0.1) # 模拟数据库查询延迟
return [f"数据项 {i}" for i in range(1000)]
def optimize_performance_demo():
"""性能优化演示"""
email = PerformanceOptimizedEmail("性能优化演示")
email.add_title("⚡ 性能优化技术演示", TextType.TITLE_LARGE)
# 演示延迟加载
lazy_widget = LazyLoadWidget()
lazy_widget.set_data_loader(create_large_dataset, "large_dataset_v1")
email.add_widget(lazy_widget)
# 演示批量组件添加
batch_widgets = []
for i in range(50):
text_widget = TextWidget()
text_widget.set_content(f"批量组件 {i + 1}")
batch_widgets.append(text_widget)
# 使用批量添加而非逐个添加
start_time = time.time()
email.add_widgets_batch(batch_widgets)
batch_time = time.time() - start_time
# 性能统计
stats_text = f"""
**性能优化结果:**
⚡ **批量处理**
• 批量添加50个组件用时: {batch_time:.3f}秒
• 预估比逐个添加快60%
🔄 **缓存优化**
• 模板缓存命中率: 95%+
• 数据查询缓存生效
📊 **内存优化**
• 延迟加载减少初始内存占用
• 组件渲染按需进行
"""
email.add_text(stats_text.strip())
return email
# 运行性能优化演示
optimized_email = optimize_performance_demo()
optimized_email.export_html("performance_optimization_demo.html")
print("✅ 性能优化演示已生成:performance_optimization_demo.html")
性能优化演示
⚡ 性能优化技术演示
Widget渲染错误: LazyLoadWidget (lazyloadwidget_9c5d7eee)
错误详情: 模板未定义
错误详情: 模板未定义
**性能优化结果:**
⚡ **批量处理**
• 批量添加50个组件用时: 0.001秒
• 预估比逐个添加快60%
🔄 **缓存优化**
• 模板缓存命中率: 95%+ (Mocked)
• 数据查询缓存生效 (Mocked)
📊 **内存优化**
• 延迟加载减少初始内存占用
• 组件渲染按需进行
性能优化特点: - 多层缓存策略 - 批量处理优化 - 延迟加载机制 - 异步渲染支持
响应式布局¶
移动设备适配¶
Python
class ResponsiveLayoutWidget(BaseWidget):
"""响应式布局组件"""
def __init__(self):
super().__init__()
self._columns = []
self._mobile_stack = True
self._gap = "20px"
def add_column(self, widget, width_desktop="1fr", width_mobile="100%"):
"""添加列"""
self._columns.append({
'widget': widget,
'width_desktop': width_desktop,
'width_mobile': width_mobile
})
return self
def set_mobile_stack(self, stack: bool):
"""设置移动端是否堆叠"""
self._mobile_stack = stack
return self
def render(self) -> str:
desktop_grid = " ".join(col['width_desktop'] for col in self._columns)
# 生成响应式CSS
responsive_css = f"""
<style>
.responsive-grid {{
display: grid;
grid-template-columns: {desktop_grid};
gap: {self._gap};
margin: 10px 0;
}}
@media (max-width: 600px) {{
.responsive-grid {{
grid-template-columns: {"1fr" if self._mobile_stack else desktop_grid};
}}
}}
.responsive-column {{
min-width: 0; /* 防止内容溢出 */
}}
</style>
"""
# 生成列内容
columns_html = ""
for col in self._columns:
columns_html += f"""
<div class="responsive-column">
{col['widget'].render()}
</div>
"""
return f"""
{responsive_css}
<div class="responsive-grid">
{columns_html}
</div>
"""
# 响应式布局演示
email = Email("响应式布局演示")
email.add_title("📱 响应式布局演示", TextType.TITLE_LARGE)
# 创建响应式布局
responsive_layout = ResponsiveLayoutWidget()
# 左列:指标卡片
left_widget = MetricCardWidget()
left_widget.set_title("月度收入") \
.set_value("¥1,250,000") \
.set_change(15.8) \
.set_color_scheme("primary")
# 右列:状态信息
right_widget = TextWidget()
right_widget.set_content("""
**系统状态摘要**
✅ 所有服务正常运行
📊 数据同步完成
🔒 安全检查通过
📈 性能指标良好
""")
# 添加到响应式布局
responsive_layout.add_column(left_widget, "2fr", "100%") \
.add_column(right_widget, "1fr", "100%") \
.set_mobile_stack(True)
email.add_widget(responsive_layout)
# 添加移动优化说明
mobile_info = """
**📱 移动端优化特性:**
• **自适应布局** - 桌面端多列,移动端单列
• **触摸友好** - 按钮和链接适合手指操作
• **字体缩放** - 文字大小自动适配屏幕
• **图片响应** - 图片自动缩放适配容器
"""
email.add_text(mobile_info.strip())
email.export_html("responsive_layout_demo.html")
print("✅ 响应式布局演示已生成:responsive_layout_demo.html")
响应式布局演示
📱 响应式布局演示
Widget渲染错误: ResponsiveLayoutWidget (responsivelayoutwidget_b513ce08)
错误详情: 模板未定义
错误详情: 模板未定义
**📱 移动端优化特性:**
• **自适应布局** - 桌面端多列,移动端单列
• **触摸友好** - 按钮和链接适合手指操作
• **字体缩放** - 文字大小自动适配屏幕
• **图片响应** - 图片自动缩放适配容器
响应式特点: - CSS Grid 布局系统 - 移动端适配策略 - 触摸友好设计 - 自适应组件尺寸
学习总结¶
通过高级示例,您已经掌握了:
🛠️ 高级技能¶
- 自定义组件 - 继承 BaseWidget 创建专业组件
- 主题系统 - 可扩展的样式配置体系
- 模板引擎 - 自定义过滤器和模板系统
- 性能优化 - 缓存、批量处理、异步渲染
🎨 设计能力¶
- 组件化开发思维
- 主题驱动的设计系统
- 响应式布局适配
- 用户体验优化
💡 架构思维¶
- 可扩展的系统设计
- 性能优化策略
- 缓存和延迟加载
- 模块化和复用性
🚀 实战应用¶
- 企业级组件库开发
- 多主题邮件系统
- 高性能报告生成
- 移动端友好设计
继续学习 实际应用,看看这些技术在真实项目中的综合运用!