- 手机预览按 iPhone 15 Pro Max 真实比例 (2.084:1) 重设计 - 钛金属渐变边框 + Dynamic Island + 前置摄像头 + 侧边按钮 - 背面摄像头模组微阴影暗示 + 多层投影深度效果 - iOS 17 风格状态栏 (信号/WiFi/电池 SVG 图标) - 样式模板从 14 种扩展到 27 种 - 新增: 成功/危险/强调提示框、时间线、步骤流程、对比卡片、问答、进度条、引言卡片等
267 lines
19 KiB
TypeScript
267 lines
19 KiB
TypeScript
/**
|
||
* 文章编辑器样式模板数据
|
||
* 所有 HTML 片段使用内联样式,通过 wangEditor 自定义 styled-block 模块保留样式。
|
||
* 模板中使用 {{primary}} / {{primaryLight}} 占位符,由 applyTheme() 替换为实际颜色值。
|
||
*/
|
||
|
||
export interface StyleTemplate {
|
||
id: string;
|
||
name: string;
|
||
category: 'heading' | 'content' | 'block';
|
||
preview: string;
|
||
html: string;
|
||
}
|
||
|
||
export interface ColorTheme {
|
||
id: string;
|
||
name: string;
|
||
primary: string;
|
||
primaryLight: string;
|
||
}
|
||
|
||
export const COLOR_THEMES: ColorTheme[] = [
|
||
{ id: 'green', name: '清新绿', primary: '#16a34a', primaryLight: '#dcfce7' },
|
||
{ id: 'blue', name: '专业蓝', primary: '#2563eb', primaryLight: '#dbeafe' },
|
||
{ id: 'red', name: '暖橘红', primary: '#C4623A', primaryLight: '#F0DDD4' },
|
||
{ id: 'purple', name: '雅致紫', primary: '#7c3aed', primaryLight: '#ede9fe' },
|
||
{ id: 'amber', name: '琥珀金', primary: '#d97706', primaryLight: '#fef3c7' },
|
||
];
|
||
|
||
const W = 'data-w-e-type="styled-block"';
|
||
|
||
// ═══════════════════════════════════════
|
||
// 标题样式 (6 种)
|
||
// ═══════════════════════════════════════
|
||
|
||
export const HEADING_TEMPLATES: StyleTemplate[] = [
|
||
{
|
||
id: 'heading-classic',
|
||
name: '经典 · 左边框',
|
||
category: 'heading',
|
||
preview: '▎左边框标题',
|
||
html: `<div ${W} style="border-left: 4px solid {{primary}}; padding-left: 12px; font-size: 20px; font-weight: 700; color: #1a1a1a; margin: 24px 0 12px;">标题文本</div>`,
|
||
},
|
||
{
|
||
id: 'heading-underline',
|
||
name: '简约 · 下划线',
|
||
category: 'heading',
|
||
preview: '标题 ──────',
|
||
html: `<div ${W} style="border-bottom: 2px solid {{primary}}; padding-bottom: 8px; font-size: 20px; font-weight: 700; color: #1a1a1a; margin: 24px 0 12px; display: inline-block;">标题文本</div>`,
|
||
},
|
||
{
|
||
id: 'heading-badge',
|
||
name: '圆标 · 标签式',
|
||
category: 'heading',
|
||
preview: '■ 标签式标题',
|
||
html: `<div ${W} style="display: inline-block; background: {{primaryLight}}; color: {{primary}}; padding: 4px 14px; border-radius: 4px; font-size: 18px; font-weight: 700; margin: 24px 0 12px;">标题文本</div>`,
|
||
},
|
||
{
|
||
id: 'heading-centered',
|
||
name: '居中标题',
|
||
category: 'heading',
|
||
preview: '── 居中标题 ──',
|
||
html: `<div ${W} style="text-align: center; font-size: 20px; font-weight: 700; color: #1a1a1a; margin: 28px 0 12px;">标题文本</div>`,
|
||
},
|
||
{
|
||
id: 'heading-double-line',
|
||
name: '双线 · 上下框',
|
||
category: 'heading',
|
||
preview: '───────\n标题\n───────',
|
||
html: `<div ${W} style="text-align: center; margin: 24px 0 12px; padding: 10px 0; border-top: 2px solid {{primary}}; border-bottom: 2px solid {{primary}}; font-size: 20px; font-weight: 700; color: #1a1a1a;">标题文本</div>`,
|
||
},
|
||
{
|
||
id: 'heading-accent-bar',
|
||
name: '色带 · 顶部色条',
|
||
category: 'heading',
|
||
preview: '━━━\n标题文本',
|
||
html: `<div ${W} style="margin: 24px 0 12px; padding: 12px 0 0; border-top: 4px solid {{primary}}; font-size: 20px; font-weight: 700; color: #1a1a1a;">标题文本</div>`,
|
||
},
|
||
];
|
||
|
||
// ═══════════════════════════════════════
|
||
// 内容模板 (13 种)
|
||
// ═══════════════════════════════════════
|
||
|
||
export const CONTENT_TEMPLATES: StyleTemplate[] = [
|
||
{
|
||
id: 'blockquote',
|
||
name: '引用框',
|
||
category: 'content',
|
||
preview: '▎引用文字...',
|
||
html: `<div ${W} style="border-left: 3px solid {{primary}}; padding: 12px 16px; margin: 16px 0; background: #f9fafb; border-radius: 0 8px 8px 0; font-size: 15px; line-height: 1.8; color: #5a554f; font-style: italic;">引用内容请在此处编辑</div>`,
|
||
},
|
||
{
|
||
id: 'tip-warning',
|
||
name: '提示框 · 警告',
|
||
category: 'content',
|
||
preview: '⚠ 注意事项',
|
||
html: `<div ${W} style="background: #fffbeb; border: 1px solid #fde68a; border-radius: 8px; padding: 14px 16px; margin: 16px 0; font-size: 15px; line-height: 1.8; color: #92400e;"><strong>⚠ 注意事项:</strong>请在此处编辑警告内容。</div>`,
|
||
},
|
||
{
|
||
id: 'tip-info',
|
||
name: '提示框 · 信息',
|
||
category: 'content',
|
||
preview: 'ℹ 补充说明',
|
||
html: `<div ${W} style="background: #eff6ff; border: 1px solid #bfdbfe; border-radius: 8px; padding: 14px 16px; margin: 16px 0; font-size: 15px; line-height: 1.8; color: #1e40af;"><strong>ℹ 补充说明:</strong>请在此处编辑信息内容。</div>`,
|
||
},
|
||
{
|
||
id: 'tip-success',
|
||
name: '提示框 · 正确',
|
||
category: 'content',
|
||
preview: '✓ 正确做法',
|
||
html: `<div ${W} style="background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 8px; padding: 14px 16px; margin: 16px 0; font-size: 15px; line-height: 1.8; color: #166534;"><strong>✓ 正确做法:</strong>请在此处编辑推荐内容。</div>`,
|
||
},
|
||
{
|
||
id: 'tip-danger',
|
||
name: '提示框 · 危险',
|
||
category: 'content',
|
||
preview: '✕ 严禁事项',
|
||
html: `<div ${W} style="background: #fef2f2; border: 1px solid #fecaca; border-radius: 8px; padding: 14px 16px; margin: 16px 0; font-size: 15px; line-height: 1.8; color: #991b1b;"><strong>✕ 严禁事项:</strong>请在此处编辑危险警告内容。</div>`,
|
||
},
|
||
{
|
||
id: 'tip-primary',
|
||
name: '提示框 · 强调',
|
||
category: 'content',
|
||
preview: '★ 重点强调',
|
||
html: `<div ${W} style="background: {{primaryLight}}; border: 1px solid {{primary}}; border-radius: 8px; padding: 14px 16px; margin: 16px 0; font-size: 15px; line-height: 1.8; color: #1a1a1a;"><strong style="color: {{primary}};">★ 重点强调:</strong>请在此处编辑重点内容。</div>`,
|
||
},
|
||
{
|
||
id: 'list-ordered',
|
||
name: '有序列表',
|
||
category: 'content',
|
||
preview: '① ② ③',
|
||
html: `<div ${W} style="padding-left: 20px; margin: 16px 0; font-size: 16px; line-height: 2; color: #3a3a3c;"><div style="position: relative; padding-left: 8px; margin-bottom: 4px;"><span style="position: absolute; left: -20px; color: {{primary}}; font-weight: 600;">1.</span>第一项内容</div><div style="position: relative; padding-left: 8px; margin-bottom: 4px;"><span style="position: absolute; left: -20px; color: {{primary}}; font-weight: 600;">2.</span>第二项内容</div><div style="position: relative; padding-left: 8px; margin-bottom: 4px;"><span style="position: absolute; left: -20px; color: {{primary}}; font-weight: 600;">3.</span>第三项内容</div></div>`,
|
||
},
|
||
{
|
||
id: 'list-unordered',
|
||
name: '无序列表',
|
||
category: 'content',
|
||
preview: '• • •',
|
||
html: `<div ${W} style="padding-left: 20px; margin: 16px 0; font-size: 16px; line-height: 2; color: #3a3a3c;"><div style="position: relative; padding-left: 8px; margin-bottom: 4px;"><span style="position: absolute; left: -14px; color: {{primary}};">●</span>第一项内容</div><div style="position: relative; padding-left: 8px; margin-bottom: 4px;"><span style="position: absolute; left: -14px; color: {{primary}};">●</span>第二项内容</div><div style="position: relative; padding-left: 8px; margin-bottom: 4px;"><span style="position: absolute; left: -14px; color: {{primary}};">●</span>第三项内容</div></div>`,
|
||
},
|
||
{
|
||
id: 'card-image-text',
|
||
name: '图文卡片',
|
||
category: 'content',
|
||
preview: '[图] 文字说明',
|
||
html: `<div ${W} style="display: flex; gap: 12px; margin: 16px 0; padding: 12px; background: #f9fafb; border-radius: 8px; align-items: center;"><div style="width: 100px; height: 80px; background: #e5e7eb; border-radius: 6px; display: flex; align-items: center; justify-content: center; color: #9ca3af; font-size: 12px; flex-shrink: 0;">图片</div><div style="flex: 1; font-size: 14px; line-height: 1.8; color: #3a3a3c;">图文卡片的文字描述内容请在此处编辑。</div></div>`,
|
||
},
|
||
{
|
||
id: 'card-data',
|
||
name: '数据卡片',
|
||
category: 'content',
|
||
preview: '血压 120/80',
|
||
html: `<div ${W} style="display: flex; gap: 12px; margin: 16px 0; flex-wrap: wrap;"><div style="flex: 1; min-width: 120px; background: {{primaryLight}}; border-radius: 8px; padding: 14px; text-align: center;"><div style="font-size: 24px; font-weight: 700; color: {{primary}};">120/80</div><div style="font-size: 13px; color: #5a554f; margin-top: 4px;">血压 (mmHg)</div></div><div style="flex: 1; min-width: 120px; background: #f3f4f6; border-radius: 8px; padding: 14px; text-align: center;"><div style="font-size: 24px; font-weight: 700; color: #1a1a1a;">72</div><div style="font-size: 13px; color: #5a554f; margin-top: 4px;">心率 (bpm)</div></div></div>`,
|
||
},
|
||
{
|
||
id: 'timeline',
|
||
name: '时间线',
|
||
category: 'content',
|
||
preview: '●── 第一步\n●── 第二步',
|
||
html: `<div ${W} style="margin: 16px 0; padding-left: 20px; border-left: 2px solid {{primary}};"><div style="position: relative; padding: 0 0 20px 16px;"><div style="position: absolute; left: -27px; top: 2px; width: 12px; height: 12px; border-radius: 50%; background: {{primary}};"></div><div style="font-size: 14px; font-weight: 600; color: #1a1a1a; margin-bottom: 2px;">2024年1月</div><div style="font-size: 14px; color: #5a554f; line-height: 1.6;">第一阶段内容描述</div></div><div style="position: relative; padding: 0 0 20px 16px;"><div style="position: absolute; left: -27px; top: 2px; width: 12px; height: 12px; border-radius: 50%; background: {{primary}};"></div><div style="font-size: 14px; font-weight: 600; color: #1a1a1a; margin-bottom: 2px;">2024年3月</div><div style="font-size: 14px; color: #5a554f; line-height: 1.6;">第二阶段内容描述</div></div><div style="position: relative; padding: 0 0 0 16px;"><div style="position: absolute; left: -27px; top: 2px; width: 12px; height: 12px; border-radius: 50%; background: {{primary}};"></div><div style="font-size: 14px; font-weight: 600; color: #1a1a1a; margin-bottom: 2px;">2024年6月</div><div style="font-size: 14px; color: #5a554f; line-height: 1.6;">第三阶段内容描述</div></div></div>`,
|
||
},
|
||
{
|
||
id: 'steps',
|
||
name: '步骤流程',
|
||
category: 'content',
|
||
preview: '➊ → ➋ → ➌',
|
||
html: `<div ${W} style="margin: 16px 0;"><div style="display: flex; align-items: flex-start; margin-bottom: 16px;"><div style="width: 28px; height: 28px; background: {{primary}}; color: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 700; flex-shrink: 0; margin-right: 12px;">1</div><div style="flex: 1; padding-top: 4px;"><div style="font-size: 15px; font-weight: 600; color: #1a1a1a; margin-bottom: 2px;">第一步标题</div><div style="font-size: 14px; color: #5a554f; line-height: 1.6;">步骤一的详细说明内容</div></div></div><div style="display: flex; align-items: flex-start; margin-bottom: 16px;"><div style="width: 28px; height: 28px; background: {{primary}}; color: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 700; flex-shrink: 0; margin-right: 12px;">2</div><div style="flex: 1; padding-top: 4px;"><div style="font-size: 15px; font-weight: 600; color: #1a1a1a; margin-bottom: 2px;">第二步标题</div><div style="font-size: 14px; color: #5a554f; line-height: 1.6;">步骤二的详细说明内容</div></div></div><div style="display: flex; align-items: flex-start;"><div style="width: 28px; height: 28px; background: {{primary}}; color: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 700; flex-shrink: 0; margin-right: 12px;">3</div><div style="flex: 1; padding-top: 4px;"><div style="font-size: 15px; font-weight: 600; color: #1a1a1a; margin-bottom: 2px;">第三步标题</div><div style="font-size: 14px; color: #5a554f; line-height: 1.6;">步骤三的详细说明内容</div></div></div></div>`,
|
||
},
|
||
{
|
||
id: 'comparison',
|
||
name: '对比卡片',
|
||
category: 'content',
|
||
preview: '✓ 推荐 ✕ 避免',
|
||
html: `<div ${W} style="display: flex; gap: 12px; margin: 16px 0; flex-wrap: wrap;"><div style="flex: 1; min-width: 140px; background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 8px; padding: 14px;"><div style="font-size: 15px; font-weight: 700; color: #166534; margin-bottom: 8px;">✓ 推荐做法</div><div style="font-size: 14px; color: #166534; line-height: 1.8;">推荐内容第一项<br/>推荐内容第二项<br/>推荐内容第三项</div></div><div style="flex: 1; min-width: 140px; background: #fef2f2; border: 1px solid #fecaca; border-radius: 8px; padding: 14px;"><div style="font-size: 15px; font-weight: 700; color: #991b1b; margin-bottom: 8px;">✕ 应该避免</div><div style="font-size: 14px; color: #991b1b; line-height: 1.8;">避免内容第一项<br/>避免内容第二项<br/>避免内容第三项</div></div></div>`,
|
||
},
|
||
{
|
||
id: 'faq',
|
||
name: '问答卡片',
|
||
category: 'content',
|
||
preview: 'Q: 问题\nA: 回答',
|
||
html: `<div ${W} style="margin: 16px 0; background: #f9fafb; border-radius: 8px; overflow: hidden;"><div style="background: {{primaryLight}}; padding: 10px 16px; font-size: 15px; font-weight: 600; color: {{primary}};">Q:这里填写常见问题?</div><div style="padding: 12px 16px; font-size: 14px; line-height: 1.8; color: #3a3a3c;">A:这里填写问题的详细回答内容,帮助读者理解相关知识。</div></div>`,
|
||
},
|
||
{
|
||
id: 'highlight-text',
|
||
name: '重点高亮',
|
||
category: 'content',
|
||
preview: '▸ 高亮重点内容',
|
||
html: `<div ${W} style="margin: 16px 0; padding: 12px 16px; background: {{primaryLight}}; border-radius: 8px; font-size: 15px; line-height: 1.8; color: #1a1a1a; border-left: 4px solid {{primary}};"><strong>重点:</strong>这里是需要高亮强调的关键内容。</div>`,
|
||
},
|
||
{
|
||
id: 'key-value',
|
||
name: '键值对列表',
|
||
category: 'content',
|
||
preview: '指标: 数值',
|
||
html: `<div ${W} style="margin: 16px 0; background: #f9fafb; border-radius: 8px; overflow: hidden; font-size: 14px;"><div style="display: flex; padding: 10px 16px; border-bottom: 1px solid #e5e7eb;"><div style="width: 100px; color: #5a554f; flex-shrink: 0;">检查项目</div><div style="flex: 1; font-weight: 600; color: #1a1a1a;">检测结果</div></div><div style="display: flex; padding: 10px 16px; border-bottom: 1px solid #e5e7eb; background: #fff;"><div style="width: 100px; color: #5a554f; flex-shrink: 0;">血红蛋白</div><div style="flex: 1; font-weight: 600; color: {{primary}};">110 g/L</div></div><div style="display: flex; padding: 10px 16px; border-bottom: 1px solid #e5e7eb;"><div style="width: 100px; color: #5a554f; flex-shrink: 0;">血清白蛋白</div><div style="flex: 1; font-weight: 600; color: {{primary}};">38 g/L</div></div><div style="display: flex; padding: 10px 16px; background: #fff;"><div style="width: 100px; color: #5a554f; flex-shrink: 0;">血钾</div><div style="flex: 1; font-weight: 600; color: #1a1a1a;">4.2 mmol/L</div></div></div>`,
|
||
},
|
||
];
|
||
|
||
// ═══════════════════════════════════════
|
||
// 区块组件 (6 种)
|
||
// ═══════════════════════════════════════
|
||
|
||
export const BLOCK_TEMPLATES: StyleTemplate[] = [
|
||
{
|
||
id: 'divider',
|
||
name: '分割线 · 虚线',
|
||
category: 'block',
|
||
preview: '─ ─ ─ ─',
|
||
html: `<div ${W} style="border: none; border-top: 1px dashed #d1d5db; margin: 24px 0; height: 0;"></div>`,
|
||
},
|
||
{
|
||
id: 'divider-gradient',
|
||
name: '分割线 · 渐变',
|
||
category: 'block',
|
||
preview: '━━━━━━━━',
|
||
html: `<div ${W} style="border: none; height: 2px; margin: 24px 0; background: linear-gradient(90deg, transparent, {{primary}}, transparent);"></div>`,
|
||
},
|
||
{
|
||
id: 'section-header',
|
||
name: '章节编号',
|
||
category: 'block',
|
||
preview: '§ 带编号章节',
|
||
html: `<div ${W} style="margin: 24px 0 12px; display: flex; align-items: center; gap: 10px;"><span style="display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; background: {{primary}}; color: #fff; border-radius: 50%; font-size: 14px; font-weight: 700; flex-shrink: 0;">1</span><span style="font-size: 18px; font-weight: 700; color: #1a1a1a;">章节标题</span></div>`,
|
||
},
|
||
{
|
||
id: 'table',
|
||
name: '数据表格',
|
||
category: 'block',
|
||
preview: '⊞ 3×2 表格',
|
||
html: `<div ${W} style="display: grid; grid-template-columns: 1fr 1fr 1fr; border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden; margin: 16px 0; font-size: 14px;"><div style="background: {{primaryLight}}; padding: 10px 12px; font-weight: 600; color: {{primary}}; border-bottom: 1px solid #e5e7eb; border-right: 1px solid #e5e7eb;">项目</div><div style="background: {{primaryLight}}; padding: 10px 12px; font-weight: 600; color: {{primary}}; border-bottom: 1px solid #e5e7eb; border-right: 1px solid #e5e7eb;">数值</div><div style="background: {{primaryLight}}; padding: 10px 12px; font-weight: 600; color: {{primary}}; border-bottom: 1px solid #e5e7eb;">备注</div><div style="padding: 10px 12px; border-bottom: 1px solid #e5e7eb; border-right: 1px solid #e5e7eb;">收缩压</div><div style="padding: 10px 12px; border-bottom: 1px solid #e5e7eb; border-right: 1px solid #e5e7eb;">120 mmHg</div><div style="padding: 10px 12px; border-bottom: 1px solid #e5e7eb;">正常</div><div style="background: #f9fafb; padding: 10px 12px; border-right: 1px solid #e5e7eb;">舒张压</div><div style="background: #f9fafb; padding: 10px 12px; border-right: 1px solid #e5e7eb;">80 mmHg</div><div style="background: #f9fafb; padding: 10px 12px;">正常</div></div>`,
|
||
},
|
||
{
|
||
id: 'progress',
|
||
name: '进度指示',
|
||
category: 'block',
|
||
preview: '█████░░░ 65%',
|
||
html: `<div ${W} style="margin: 16px 0;"><div style="display: flex; justify-content: space-between; font-size: 13px; margin-bottom: 6px;"><span style="color: #1a1a1a; font-weight: 600;">治疗进度</span><span style="color: {{primary}}; font-weight: 700;">65%</span></div><div style="background: #e5e7eb; border-radius: 99px; height: 8px; overflow: hidden;"><div style="background: {{primary}}; height: 100%; width: 65%; border-radius: 99px;"></div></div></div>`,
|
||
},
|
||
{
|
||
id: 'quote-card',
|
||
name: '引言卡片',
|
||
category: 'block',
|
||
preview: '「」引用名言',
|
||
html: `<div ${W} style="margin: 20px 0; padding: 20px; background: linear-gradient(135deg, {{primaryLight}}, #f9fafb); border-radius: 12px; position: relative;"><div style="font-size: 36px; color: {{primary}}; opacity: 0.3; line-height: 1; font-family: Georgia, serif;">"</div><div style="font-size: 15px; color: #3a3a3c; line-height: 1.8; margin-top: -8px; font-style: italic;">这里填写引用的名言或重要语句。</div><div style="margin-top: 10px; font-size: 13px; color: #5a554f; font-weight: 500;">—— 作者名</div></div>`,
|
||
},
|
||
];
|
||
|
||
/** 所有模板合并列表 */
|
||
export const ALL_TEMPLATES: StyleTemplate[] = [
|
||
...HEADING_TEMPLATES,
|
||
...CONTENT_TEMPLATES,
|
||
...BLOCK_TEMPLATES,
|
||
];
|
||
|
||
/** 将模板 HTML 中的颜色占位符替换为主题实际颜色值 */
|
||
export function applyTheme(html: string, theme: ColorTheme): string {
|
||
return html
|
||
.replaceAll('{{primary}}', theme.primary)
|
||
.replaceAll('{{primaryLight}}', theme.primaryLight);
|
||
}
|
||
|
||
/** 根据 ID 查找颜色主题 */
|
||
export function getColorTheme(themeId: string): ColorTheme {
|
||
return COLOR_THEMES.find((t) => t.id === themeId) ?? COLOR_THEMES[0];
|
||
}
|