Files
argon-theme/.kiro/specs/global-ui-optimization/design.md
nanhaoluo f8d7c79b86 feat: 全局 UI 优化与邮件模板系统
- 新增动画系统 CSS 变量(时长、缓动函数、状态层透明度)
- 新增 prefers-reduced-motion 媒体查询支持
- 优化按钮组件样式,移除渐变背景,添加涟漪效果
- 优化分享按钮错落有致的展开动画
- 优化评论区展开动画效果
- 新增设置面板 Material 3 风格分段控件
- 新增玻璃拟态(Glassmorphism)主题变体
- 新增新拟态(Neumorphism)主题变体
- 新增邮件模板系统(base.php、comment-notify.php、reply-notify.php)
- 新增邮件模板后台设置(主题色、Logo、社交链接、预览功能)
- 集成邮件模板到评论回复通知
- 版本更新至 1.5.0
2026-01-11 22:13:59 +08:00

872 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Design Document: Global UI Optimization
## Overview
本设计文档描述 Argon WordPress 主题的全局 UI 优化方案,参考 Apple Human Interface Guidelines 和 Material Design 3 设计规范。优化重点包括:按钮样式现代化、设置面板重构、分享按钮动画增强、评论展开动画优化,以及新增多种设计风格选项。
## Architecture
### 设计系统架构
```
┌─────────────────────────────────────────────────────────────┐
│ CSS Variables Layer │
│ (动画时长、缓动函数、颜色、圆角、阴影等设计令牌) │
├─────────────────────────────────────────────────────────────┤
│ Base Components Layer │
│ (按钮、卡片、输入框等基础组件样式) │
├─────────────────────────────────────────────────────────────┤
│ Feature Components Layer │
│ (设置面板、分享按钮、评论切换等功能组件) │
├─────────────────────────────────────────────────────────────┤
│ Theme Variants Layer │
│ (玻璃拟态、新拟态、Material 3 等主题变体) │
└─────────────────────────────────────────────────────────────┘
```
### 文件结构
```
style.css # 主样式文件(修改)
argontheme.js # 主脚本文件(修改)
functions.php # 主函数文件(修改 - 添加邮件模板函数)
settings.php # 设置页面(修改 - 添加邮件模板设置)
template-parts/
└── post-actions.php # 文章操作按钮模板(修改)
email-templates/
└── base.php # 邮件基础模板(新增)
└── comment-notify.php # 评论通知模板(新增)
└── reply-notify.php # 回复通知模板(新增)
```
## Components and Interfaces
### 1. 动画系统 CSS 变量
```css
:root {
/* 动画时长 */
--animation-fast: 150ms;
--animation-normal: 250ms;
--animation-slow: 400ms;
--animation-slower: 600ms;
/* 缓动函数 - Material 3 标准 */
--ease-standard: cubic-bezier(0.2, 0, 0, 1);
--ease-standard-decelerate: cubic-bezier(0, 0, 0, 1);
--ease-standard-accelerate: cubic-bezier(0.3, 0, 1, 1);
--ease-emphasized: cubic-bezier(0.2, 0, 0, 1);
--ease-emphasized-decelerate: cubic-bezier(0.05, 0.7, 0.1, 1);
--ease-emphasized-accelerate: cubic-bezier(0.3, 0, 0.8, 0.15);
/* 弹性缓动 */
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
--ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
/* 状态层透明度 - Material 3 */
--state-hover-opacity: 0.08;
--state-focus-opacity: 0.12;
--state-pressed-opacity: 0.12;
--state-dragged-opacity: 0.16;
}
```
### 2. 按钮组件设计
#### 主要按钮 (Filled Button)
```css
.btn-primary {
background-color: var(--themecolor);
border: none;
border-radius: var(--card-radius);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
transition:
background-color var(--animation-fast) var(--ease-standard),
box-shadow var(--animation-fast) var(--ease-standard),
transform var(--animation-fast) var(--ease-standard);
position: relative;
overflow: hidden;
}
.btn-primary:hover {
background-color: var(--themecolor-dark);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
}
.btn-primary:active {
background-color: var(--themecolor-dark2);
transform: scale(0.98);
}
```
#### 涟漪效果 (Ripple Effect)
```css
.btn-ripple {
position: relative;
overflow: hidden;
}
.btn-ripple::after {
content: '';
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
pointer-events: none;
background-image: radial-gradient(circle, rgba(255,255,255,0.3) 10%, transparent 10.01%);
background-repeat: no-repeat;
background-position: 50%;
transform: scale(10, 10);
opacity: 0;
transition: transform var(--animation-slow), opacity var(--animation-normal);
}
.btn-ripple:active::after {
transform: scale(0, 0);
opacity: 1;
transition: 0s;
}
```
### 3. 设置面板设计
#### 面板容器
```css
#fabtn_blog_settings_popup {
background: var(--color-foreground);
border-radius: 16px;
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.12),
0 2px 8px rgba(0, 0, 0, 0.08);
padding: 16px 20px;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
}
```
#### 分组卡片布局
设计决策:使用分组卡片将相关设置项组织在一起,提升视觉层次和可读性。
```css
.settings-group {
background: var(--color-background);
border-radius: 12px;
padding: 12px 16px;
margin-bottom: 12px;
}
.settings-group-title {
font-size: 12px;
font-weight: 600;
color: var(--color-text-light);
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 8px;
}
.settings-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 0;
}
.settings-item + .settings-item {
border-top: 1px solid var(--color-border-light);
}
```
#### 分段控件 (Segmented Control)
```css
.segmented-control {
display: inline-flex;
background: var(--color-widgets-disabled);
border-radius: 10px;
padding: 3px;
gap: 2px;
}
.segmented-control-item {
padding: 6px 14px;
border-radius: 8px;
border: none;
background: transparent;
color: var(--color-text-deeper);
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all var(--animation-fast) var(--ease-standard);
}
.segmented-control-item.active {
background: var(--themecolor);
color: #fff;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
}
```
### 4. 分享按钮动画设计
#### 容器样式
```css
#share_container {
position: relative;
display: inline-flex;
align-items: center;
}
#share {
display: flex;
gap: 6px;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
opacity: 0;
pointer-events: none;
}
#share > a {
opacity: 0;
transform: scale(0.8) translateX(10px);
}
```
#### 展开动画
```css
#share_container.opened #share {
opacity: 1;
pointer-events: auto;
}
#share_container.opened #share > a {
opacity: 1;
transform: scale(1) translateX(0);
transition:
opacity var(--animation-normal) var(--ease-emphasized-decelerate),
transform var(--animation-normal) var(--ease-spring);
}
/* 错落动画延迟 */
#share_container.opened #share > a:nth-child(1) { transition-delay: 0ms; }
#share_container.opened #share > a:nth-child(2) { transition-delay: 30ms; }
#share_container.opened #share > a:nth-child(3) { transition-delay: 60ms; }
#share_container.opened #share > a:nth-child(4) { transition-delay: 90ms; }
#share_container.opened #share > a:nth-child(5) { transition-delay: 120ms; }
#share_container.opened #share > a:nth-child(6) { transition-delay: 150ms; }
#share_container.opened #share > a:nth-child(7) { transition-delay: 180ms; }
#share_container.opened #share > a:nth-child(8) { transition-delay: 210ms; }
```
#### 主按钮变换
```css
#share_show {
transition:
transform var(--animation-normal) var(--ease-standard),
opacity var(--animation-normal) var(--ease-standard);
}
#share_container.opened #share_show {
transform: rotate(45deg) scale(0.9);
opacity: 0.7;
}
```
#### 点击外部收起逻辑
设计决策:使用事件委托监听 document 点击事件,判断点击目标是否在分享容器外部。
```javascript
// 点击外部收起分享面板
document.addEventListener('click', function(e) {
const shareContainer = document.getElementById('share_container');
if (shareContainer && shareContainer.classList.contains('opened')) {
// 检查点击目标是否在分享容器外部
if (!shareContainer.contains(e.target)) {
shareContainer.classList.remove('opened');
}
}
});
```
### 5. 评论展开动画设计
#### 评论区容器
```css
#comments, #post_comment {
transition:
max-height var(--animation-slow) var(--ease-emphasized),
opacity var(--animation-normal) var(--ease-standard),
margin var(--animation-slow) var(--ease-standard),
padding var(--animation-slow) var(--ease-standard);
overflow: hidden;
will-change: max-height, opacity;
}
#comments.comments-collapsed,
#post_comment.comments-collapsed {
max-height: 0 !important;
opacity: 0;
margin-top: 0 !important;
margin-bottom: 0 !important;
padding-top: 0 !important;
padding-bottom: 0 !important;
border: none !important;
}
#comments:not(.comments-collapsed),
#post_comment:not(.comments-collapsed) {
max-height: 9999px;
opacity: 1;
}
```
#### 切换按钮图标动画
```css
#comments_toggle .btn-inner--icon i {
transition: transform var(--animation-normal) var(--ease-spring);
}
#comments_toggle.expanded .btn-inner--icon i {
transform: rotate(180deg);
}
```
#### 折叠反向动画
设计决策折叠动画使用与展开相同的过渡属性CSS transition 会自动处理反向动画。通过调整缓动函数实现自然的收起效果。
```css
/* 折叠状态 - 使用 accelerate 缓动使收起更自然 */
#comments.comments-collapsed,
#post_comment.comments-collapsed {
transition:
max-height var(--animation-slow) var(--ease-emphasized-accelerate),
opacity var(--animation-fast) var(--ease-standard-accelerate),
margin var(--animation-slow) var(--ease-standard),
padding var(--animation-slow) var(--ease-standard);
}
```
### 6. 主题变体设计
#### 悬停效果增强
设计决策:为所有可交互元素添加统一的悬停效果,使用微妙的缩放和阴影变化提升交互反馈。
```css
/* 通用悬停效果 */
.card:hover,
.btn:hover {
transform: translateY(-1px);
box-shadow:
0 4px 12px rgba(0, 0, 0, 0.1),
0 2px 4px rgba(0, 0, 0, 0.06);
transition:
transform var(--animation-fast) var(--ease-standard),
box-shadow var(--animation-fast) var(--ease-standard);
}
/* 可点击元素的微缩放效果 */
.clickable:hover {
transform: scale(1.02);
}
.clickable:active {
transform: scale(0.98);
}
```
#### 玻璃拟态 (Glassmorphism)
```css
html.style-glass .card,
html.style-glass #fabtn_blog_settings_popup {
background: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(20px) saturate(180%);
-webkit-backdrop-filter: blur(20px) saturate(180%);
border: 1px solid rgba(255, 255, 255, 0.3);
}
html.darkmode.style-glass .card,
html.darkmode.style-glass #fabtn_blog_settings_popup {
background: rgba(66, 66, 66, 0.7);
border: 1px solid rgba(255, 255, 255, 0.1);
}
```
#### 新拟态 (Neumorphism)
```css
html.style-neumorphism .card {
background: var(--color-background);
box-shadow:
8px 8px 16px rgba(0, 0, 0, 0.1),
-8px -8px 16px rgba(255, 255, 255, 0.8);
border: none;
}
html.darkmode.style-neumorphism .card {
box-shadow:
8px 8px 16px rgba(0, 0, 0, 0.3),
-8px -8px 16px rgba(255, 255, 255, 0.05);
}
```
#### Material 3 动态色彩系统
设计决策:实现 Material 3 的动态色彩系统,根据主题色自动生成协调的色彩方案。使用 CSS 变量和 HSL 色彩空间实现动态计算。
```css
:root {
/* Material 3 色彩角色 - 基于主题色动态生成 */
--md-primary: var(--themecolor);
--md-on-primary: #ffffff;
--md-primary-container: var(--themecolor-light);
--md-on-primary-container: var(--themecolor-dark2);
/* 表面色彩 */
--md-surface: var(--color-background);
--md-surface-variant: var(--color-foreground);
--md-on-surface: var(--color-text);
--md-on-surface-variant: var(--color-text-light);
/* 轮廓色彩 */
--md-outline: var(--color-border);
--md-outline-variant: var(--color-border-light);
}
/* Material 3 风格组件 */
html.style-material3 .card {
background: var(--md-surface);
border-radius: 16px;
box-shadow:
0 1px 3px rgba(0, 0, 0, 0.12),
0 1px 2px rgba(0, 0, 0, 0.24);
}
html.style-material3 .btn-primary {
background: var(--md-primary);
color: var(--md-on-primary);
border-radius: 20px;
font-weight: 500;
letter-spacing: 0.1px;
}
html.style-material3 .btn-primary:hover {
box-shadow:
0 2px 4px rgba(0, 0, 0, 0.14),
0 3px 4px rgba(0, 0, 0, 0.12);
}
```
```javascript
// Material 3 动态色彩生成函数
function generateMaterial3Colors(primaryColor) {
// 将主题色转换为 HSL
const hsl = hexToHSL(primaryColor);
return {
primary: primaryColor,
primaryContainer: hslToHex(hsl.h, Math.max(hsl.s - 20, 0), Math.min(hsl.l + 30, 95)),
onPrimary: hsl.l > 50 ? '#000000' : '#ffffff',
onPrimaryContainer: hslToHex(hsl.h, hsl.s, Math.max(hsl.l - 40, 10))
};
}
```
## Data Models
### 设置存储结构
```javascript
// localStorage 存储的设置项
{
'Argon_UI_Style': 'default' | 'glass' | 'neumorphism' | 'material3',
'Argon_Animation_Reduced': 'true' | 'false',
'Argon_Use_Serif': 'true' | 'false',
'Argon_Use_Big_Shadow': 'true' | 'false',
'Argon_Filter': 'off' | 'sunset' | 'darkness' | 'grayscale'
}
```
### 邮件模板设置结构
```php
// WordPress 选项存储的邮件模板设置
[
'argon_email_theme_color' => '#5e72e4', // 主题色
'argon_email_logo_url' => '', // Logo 图片 URL
'argon_email_blog_name' => get_bloginfo('name'), // 博客名称
'argon_email_footer_text' => '', // 页脚版权信息
'argon_email_social_links' => [ // 社交链接
'twitter' => '',
'github' => '',
'weibo' => ''
]
]
```
### 7. 邮件模板系统设计
#### 设计决策
- 使用内联 CSS 确保邮件客户端兼容性(邮件客户端不支持外部样式表)
- 采用表格布局保证跨客户端一致性Outlook 等客户端对 div 布局支持有限)
- 提供简洁的后台设置界面,仅暴露必要的自定义选项
#### 模板基础结构
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body style="margin: 0; padding: 0; background-color: #f4f5f7; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;">
<table width="100%" cellpadding="0" cellspacing="0" style="background-color: #f4f5f7; padding: 40px 20px;">
<tr>
<td align="center">
<table width="600" cellpadding="0" cellspacing="0" style="max-width: 600px; width: 100%;">
<!-- 页眉 -->
<tr>
<td style="padding: 24px; text-align: center;">
{{#if logo_url}}
<img src="{{logo_url}}" alt="{{blog_name}}" style="max-height: 48px; max-width: 200px;">
{{else}}
<h1 style="margin: 0; font-size: 24px; color: {{theme_color}};">{{blog_name}}</h1>
{{/if}}
</td>
</tr>
<!-- 内容区 -->
<tr>
<td style="background: #ffffff; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.08);">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td style="padding: 32px;">
{{content}}
</td>
</tr>
</table>
</td>
</tr>
<!-- 页脚 -->
<tr>
<td style="padding: 24px; text-align: center;">
{{#if social_links}}
<p style="margin: 0 0 12px 0;">
{{#each social_links}}
<a href="{{this.url}}" style="display: inline-block; margin: 0 8px; color: #8898aa; text-decoration: none;">{{this.name}}</a>
{{/each}}
</p>
{{/if}}
<p style="margin: 0; font-size: 12px; color: #8898aa;">
{{footer_text}}
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
```
#### 评论通知邮件内容模板
```html
<h2 style="margin: 0 0 16px 0; font-size: 20px; color: #32325d;">
您的文章收到了新评论
</h2>
<p style="margin: 0 0 24px 0; color: #525f7f; line-height: 1.6;">
<strong>{{commenter_name}}</strong> 在《<a href="{{post_url}}" style="color: {{theme_color}};">{{post_title}}</a>》中发表了评论:
</p>
<div style="background: #f6f9fc; border-left: 4px solid {{theme_color}}; padding: 16px; border-radius: 4px; margin: 0 0 24px 0;">
<p style="margin: 0; color: #525f7f; line-height: 1.6;">{{comment_content}}</p>
</div>
<a href="{{comment_url}}" style="display: inline-block; background: {{theme_color}}; color: #ffffff; padding: 12px 24px; border-radius: 6px; text-decoration: none; font-weight: 500;">
查看评论
</a>
```
#### 评论回复通知邮件内容模板
```html
<h2 style="margin: 0 0 16px 0; font-size: 20px; color: #32325d;">
您的评论收到了回复
</h2>
<p style="margin: 0 0 16px 0; color: #8898aa; font-size: 14px;">
您在《<a href="{{post_url}}" style="color: {{theme_color}};">{{post_title}}</a>》的评论:
</p>
<div style="background: #f6f9fc; padding: 12px 16px; border-radius: 4px; margin: 0 0 16px 0;">
<p style="margin: 0; color: #8898aa; font-size: 14px;">{{original_comment}}</p>
</div>
<p style="margin: 0 0 16px 0; color: #525f7f;">
<strong>{{replier_name}}</strong> 回复了您:
</p>
<div style="background: #f6f9fc; border-left: 4px solid {{theme_color}}; padding: 16px; border-radius: 4px; margin: 0 0 24px 0;">
<p style="margin: 0; color: #525f7f; line-height: 1.6;">{{reply_content}}</p>
</div>
<a href="{{comment_url}}" style="display: inline-block; background: {{theme_color}}; color: #ffffff; padding: 12px 24px; border-radius: 6px; text-decoration: none; font-weight: 500;">
查看回复
</a>
```
#### 后台设置界面
```php
// 邮件模板设置区域 - 添加到 settings.php
function argon_email_settings_section() {
// 主题色选择器
add_settings_field('argon_email_theme_color', '邮件主题色', ...);
// Logo 上传
add_settings_field('argon_email_logo_url', '邮件 Logo', ...);
// 博客名称(默认使用站点名称)
add_settings_field('argon_email_blog_name', '邮件显示名称', ...);
// 页脚文本
add_settings_field('argon_email_footer_text', '页脚版权信息', ...);
// 社交链接
add_settings_field('argon_email_social_links', '社交链接', ...);
// 预览按钮
add_settings_field('argon_email_preview', '邮件预览', ...);
}
```
#### 邮件预览功能
```javascript
// AJAX 预览邮件
function previewEmail(type) {
fetch(ajaxurl, {
method: 'POST',
body: new URLSearchParams({
action: 'argon_preview_email',
type: type, // 'comment' | 'reply'
nonce: argon_email_nonce
})
})
.then(res => res.text())
.then(html => {
// 在模态框中显示预览
openPreviewModal(html);
});
}
```
#### PHP 邮件发送函数
```php
/**
* 发送统一格式的邮件
* @param string $to 收件人
* @param string $subject 主题
* @param string $content 内容 HTML
* @param string $type 邮件类型
*/
function argon_send_email($to, $subject, $content, $type = 'general') {
$template = argon_get_email_template();
$settings = argon_get_email_settings();
// 替换模板变量
$html = str_replace([
'{{theme_color}}',
'{{logo_url}}',
'{{blog_name}}',
'{{footer_text}}',
'{{content}}'
], [
$settings['theme_color'],
$settings['logo_url'],
$settings['blog_name'],
$settings['footer_text'],
$content
], $template);
// 设置邮件头
$headers = [
'Content-Type: text/html; charset=UTF-8',
'From: ' . $settings['blog_name'] . ' <' . get_option('admin_email') . '>'
];
return wp_mail($to, $subject, $html, $headers);
}
```
## Correctness Properties
*A property is a characteristic or behavior that should hold true across all valid executions of a system—essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
### Property 1: 按钮使用纯色背景
*For any* 主要按钮元素(.btn-primary, #share .btn, #comments_toggle),其 background 属性应该使用纯色var(--themecolor) 或具体颜色值),而不包含 gradient 关键字。
**Validates: Requirements 1.1, 3.6**
### Property 2: 组件使用主题色 CSS 变量
*For any* 使用主题色的组件(按钮、选中状态、链接等),其颜色相关属性应该使用 var(--themecolor) 或其派生变量(--themecolor-dark, --themecolor-light 等),而非硬编码的颜色值。
**Validates: Requirements 1.4, 2.3**
### Property 3: 动画系统 CSS 变量定义
*For any* 动画相关的 CSS 变量,:root 选择器中应该定义 --animation-fast, --animation-normal, --animation-slow 时长变量,以及 --ease-standard, --ease-emphasized, --ease-spring 等缓动函数变量。
**Validates: Requirements 5.1, 5.2**
### Property 4: 分享按钮错落动画延迟
*For any* 分享按钮容器中的子元素(#share > a每个元素应该有递增的 transition-delay 值,形成错落有致的动画效果。
**Validates: Requirements 3.2**
### Property 5: 评论区过渡动画属性
*For any* 评论区容器(#comments, #post_comment),其 transition 属性应该包含 max-height 和 opacity并使用 CSS 变量定义的动画时长。
**Validates: Requirements 4.1, 4.2, 4.4**
### Property 6: GPU 加速动画属性
*For any* 交互动画(悬停、点击、展开/收起),应该主要使用 transform 和 opacity 属性进行动画,而非 width, height, top, left 等触发重排的属性。
**Validates: Requirements 5.3**
### Property 7: 样式切换过渡动画
*For any* 主要容器元素(.card, #fabtn_blog_settings_popup),应该定义 transition 属性覆盖 background-color 和 box-shadow 的变化,以支持样式切换时的平滑过渡。
**Validates: Requirements 6.4**
### Property 8: 点击外部收起分享面板
*For any* 处于展开状态的分享面板,当用户点击分享容器外部区域时,分享面板应该收起(移除 .opened 类)。
**Validates: Requirements 3.5**
### Property 9: 悬停效果使用 transform 和 box-shadow
*For any* 可交互元素(.card, .btn的悬停状态应该使用 transform如 translateY 或 scale和 box-shadow 属性实现视觉反馈,而非改变元素尺寸或位置属性。
**Validates: Requirements 5.5**
### Property 10: Material 3 色彩变量定义
*For any* 启用 Material 3 样式的页面,:root 选择器中应该定义 --md-primary, --md-surface, --md-on-primary 等 Material 3 色彩角色变量。
**Validates: Requirements 6.3**
### Property 11: 邮件模板统一结构
*For any* 发送的邮件(评论通知、回复通知等),其 HTML 结构应该包含页眉logo/博客名)、内容区、页脚(版权信息)三个区域,且使用相同的基础模板。
**Validates: Requirements 7.1**
### Property 12: 邮件模板主题色应用
*For any* 邮件模板中的主题色元素(按钮背景、链接颜色、边框强调色),应该使用后台设置的 argon_email_theme_color 值,而非硬编码颜色。
**Validates: Requirements 7.2**
### Property 13: 邮件模板内联样式
*For any* 邮件模板的 HTML 输出所有样式应该以内联方式style 属性)应用,不依赖外部 CSS 文件或 `<style>` 标签,以确保邮件客户端兼容性。
**Validates: Requirements 7.7**
## Error Handling
### CSS 兼容性处理
1. **backdrop-filter 不支持时的降级**
- 使用 @supports 查询检测支持情况
- 降级为纯色背景加透明度
2. **CSS 变量不支持时的降级**
- 在变量值前提供硬编码的回退值
- 示例:`transition: all 250ms ease; transition: all var(--animation-normal) var(--ease-standard);`
3. **prefers-reduced-motion 处理**
- 检测用户偏好减少动画
- 将所有动画时长设为 0 或极短值
### JavaScript 错误处理
1. **localStorage 不可用**
- 使用 try-catch 包装存储操作
- 降级为内存存储或 cookie
2. **动画 API 不支持**
- 检测 Web Animations API 支持
- 降级为 CSS transition
### 邮件发送错误处理
1. **wp_mail 发送失败**
- 记录错误日志
- 返回友好的错误提示
2. **模板变量缺失**
- 提供默认值回退
- 使用站点名称作为博客名称默认值
- 使用主题色作为邮件主题色默认值
3. **图片加载失败**
- Logo 图片加载失败时显示文字博客名称
- 使用 alt 属性提供替代文本
## Testing Strategy
### 单元测试
1. **CSS 变量定义测试**
- 验证所有必需的 CSS 变量已定义
- 验证变量值格式正确
2. **样式类存在性测试**
- 验证 .style-glass, .style-neumorphism 等类已定义
- 验证 .segmented-control 组件样式已定义
3. **JavaScript 功能测试**
- 验证样式切换函数正确更新 localStorage
- 验证分享按钮展开/收起逻辑
### 属性测试
由于本功能主要涉及 CSS 样式和视觉效果,属性测试将通过以下方式进行:
1. **CSS 解析验证**
- 解析 style.css 文件
- 验证按钮背景不包含 gradient
- 验证动画属性使用 CSS 变量
2. **DOM 结构验证**
- 验证分享按钮子元素具有递增的 transition-delay
- 验证评论区容器具有正确的 transition 属性
### 视觉回归测试(可选)
1. 使用截图对比工具验证样式变更
2. 在不同浏览器中验证兼容性
### 邮件模板测试
1. **模板渲染测试**
- 验证所有模板变量正确替换
- 验证 HTML 结构完整性
2. **邮件客户端兼容性测试**
- 在 Gmail Web 端验证显示效果
- 在 Outlook 验证表格布局
- 在 Apple Mail 验证样式渲染
3. **设置功能测试**
- 验证主题色修改后邮件颜色更新
- 验证 Logo 上传和显示
- 验证预览功能正确渲染当前设置