Campaigns, Automation, Discounts, Tagging, Research Platform | 更新时间: 2026-03-02
/admin/marketing/research 为主路径;/admin/marketing/experiments 仅保留兼容重定向别名。
admin/marketing/promotion/page.tsx (6 tabs: Email Templates/SMS Templates/Email Designs/Campaigns/Triggers/Automation),
admin/marketing/promotion/email-templates/page.tsx,
admin/marketing/promotion/email-templates/editor/page.tsx,
admin/marketing/promotion/email-templates/variables/page.tsx,
admin/marketing/promotion/email-templates/preview/page.tsx,
admin/marketing/promotion/sms-templates/page.tsx,
admin/marketing/email-designs/[id]/page.tsx (Canvas Editor),
admin/marketing/email-designs/[id]/preview/page.tsx,
admin/marketing/email-designs/campaigns/page.tsx,
admin/marketing/email-designs/campaigns/[id]/page.tsx (Campaign Detail/Progress),
admin/marketing/discounts/page.tsx,
admin/marketing/guest-tagging/page.tsx (3 tabs: Overview/Guests/Definitions),
admin/marketing/messaging-settings/page.tsx,
admin/marketing/strategies/page.tsx,
admin/marketing/strategies/new/page.tsx,
admin/marketing/strategies/[id]/edit/page.tsx,
admin/marketing/research/page.tsx,
admin/marketing/research/new/page.tsx,
admin/marketing/research/[id]/page.tsx,
admin/marketing/research/[id]/edit/page.tsx,
admin/marketing/research/[id]/participants/page.tsx,
admin/marketing/research/[id]/outreach/page.tsx,
admin/marketing/research/[id]/analytics/page.tsx,
admin/marketing/analytics/page.tsx
EmailBuilderEditor.tsx,
CanvasEditor.tsx (Fabric.js),
CampaignComposer.tsx (4-step wizard),
TemplateLibrary.tsx,
VariableTree.tsx,
VariableDrawer.tsx,
VariableCascader.tsx,
VariableAutocomplete.tsx,
VariableErrorMarker.tsx,
DiscountCouponTable.tsx,
TriggerTemplatesContent.tsx,
AutomationRulesContent.tsx,
GuestTagsList.tsx,
TagStatsCard.tsx,
TagFilterPanel.tsx,
RuleBuilderModal.tsx,
CompositeTagModal.tsx,
EditTagDefinitionModal.tsx,
PreviewModal.tsx
useExperimentApi.ts (legacy alias),
useResearchApi.ts,
useTemplateVariables.ts (supports 4 schema types),
useDesignApi.ts
api/marketing.js (2000+ lines),
api/marketing/trigger-templates.js,
api/marketing/automation-rules.js,
api/discounts.js (1200+ lines),
api/templates.js (Schema API + Variable API + Validation),
api/email-template-builder.js,
api/email-designs.js,
api/experiments.js (legacy alias),
api/research.js,
api/tags.js,
services/messaging.js
schemas/variable-schemas/*.json (4 JSON: service-email, promotion-email, lifecycle-email, transactional-email),
services/templating/schema-loader.js,
services/templating/variable-engine.js,
services/templating/variable-validator.js,
services/templating/legacy-compat.js,
services/templating/context-builders/promotion-context.js,
services/templating/context-builders/service-context.js,
services/templating/context-builders/lifecycle-context.js,
services/templating/context-builders/transactional-context.js,
services/automation/execution-processor.js
| CUJ | 优先级 | 描述 | 触发角色 | 业务价值 | E2E 状态 |
|---|---|---|---|---|---|
| I1 | P0 | 折扣与优惠券管理 | admin+ | 促销 — 提升转化率 | 已覆盖 |
| I2 | P0 | 邮件模板管理 | admin+ | 沟通 — 品牌一致的邮件 | 部分覆盖 |
| I3 | P1 | SMS 模板管理 | admin+ | 触达 — 高打开率通道 | 未覆盖 |
| I4 | P0 | 营销活动发送 | admin+ | 核心 — 多渠道触达客户 | 未覆盖 |
| I5 | P1 | 自动化触发与规则 | admin+ | 效率 — 事件驱动营销 | 已覆盖 |
| I6 | P1 | 客户自动标签 | admin+ | 精准 — 行为驱动分群 | 未覆盖 |
| I7 | P2 | 营销实验 A/B 测试 | admin+ | 数据 — 科学决策 | 已覆盖 |
| I8 | P2 | 营销策略管理 | admin+ | 规划 — 多渠道策略编排 | 已覆盖 |
| I9 | P2 | 用户研究平台 | admin+ | 洞察 — 客户反馈收集 | 已覆盖 |
| I10 | P1 | 营销分析 | admin+ | 度量 — 效果追踪 | 已覆盖 |
flowchart TD
subgraph Content["内容层"]
ET["邮件模板 (Code)"]
ED["邮件设计 (Canvas)"]
ST["SMS 模板"]
VB["可视化编辑器"]
end
subgraph Schema["Schema SSOT 层"]
SS["变量 Schema (4 types)"]
SL["Schema Loader"]
LC["Legacy Compat"]
VV["变量验证器"]
CB["Context Builders (4)"]
end
subgraph Targeting["定向层"]
TAG["自动标签"]
SEG["客户分群"]
DISC["折扣/优惠券"]
end
subgraph Execution["执行层"]
CAMP["营销活动"]
CC["Campaign Composer"]
AUTO["自动化规则"]
TRIG["触发器模板"]
end
subgraph Intelligence["分析层"]
EXP["A/B 实验"]
STR["营销策略"]
RES["用户研究"]
ANA["营销分析"]
end
ET --> CAMP
ED --> CC
CC --> CAMP
ST --> CAMP
VB --> ET
VB --> ED
SS --> SL
SL --> VV
SL --> CB
LC --> CB
CB --> ET
CB --> ED
CB --> ST
TAG --> SEG
SEG --> CAMP
DISC --> CAMP
TRIG --> AUTO
ET --> AUTO
ST --> AUTO
CAMP --> ANA
EXP --> ANA
STR --> CAMP
style CAMP fill:#c62828,stroke:#b71c1c,color:#fff
style AUTO fill:#e65100,stroke:#bf360c,color:#fff
style TAG fill:#1565c0,stroke:#0d47a1,color:#fff
style EXP fill:#6a1b9a,stroke:#4a148c,color:#fff
style SS fill:#00695c,stroke:#004d40,color:#fff
style CC fill:#ad1457,stroke:#880e4f,color:#fff
backend/schemas/variable-schemas/*.json)。
前端通过 GET /api/templates/schemas/:type 获取,后端通过 schema-loader.js 加载。
旧的平面变量名(如 customer_name)通过 legacy-compat.js 自动映射到嵌套格式。
| Schema Type | 用途 | 模板类别映射 | Schema 文件 |
|---|---|---|---|
service_email | 服务通知(预约确认/提醒/跟进) | category: notification | service-email.json |
promotion_email | 营销推广(优惠券/活动邀请) | category: promotional | promotion-email.json |
lifecycle_email | 生命周期(生日祝福/流失召回) | category: lifecycle | lifecycle-email.json |
transactional_email | 交易通知(支付收据/退款通知) | category: transactional | transactional-email.json |
| 变量分类 | 前缀 | 示例 | 可用 Schema |
|---|---|---|---|
| Guest (基本) | guest.* | {{guest.name}}, {{guest.email}}, {{guest.phone}} | 全部 4 种 |
| Guest (忠诚度) | guest.* | {{guest.loyalty_points}}, {{guest.loyalty_tier}} | promotion, lifecycle |
| Guest (生命周期) | guest.* | {{guest.birthday}}, {{guest.years_as_customer}}, {{guest.days_since_visit}} | lifecycle |
| Appointment | appointment.* | {{appointment.date}}, {{appointment.time}}, {{appointment.status}} | service_email |
| Services[] | services.* | {{#each services}}{{name}} - {{price}}{{/each}} | service_email |
| Guests[] | guests.* | {{#each guests}}{{name}}{{/each}} | service_email |
| Technician | technician.* | {{technician.name}}, {{technician.phone}} | service_email |
| Campaign | campaign.* | {{campaign.discount_code}}, {{campaign.expiry_date}} | promotion_email |
| Transaction | transaction.* | {{transaction.amount}}, {{transaction.receipt_url}} | transactional_email |
| Transaction Items[] | transaction.items.* | {{#each transaction.items}}{{name}} ${{price}}{{/each}} | transactional_email |
| Store | store.* | {{store.name}}, {{store.address}}, {{store.phone}} | 全部 4 种 |
| System | system.* | {{system.booking_link}}, {{system.unsubscribe_link}} | 全部 4 种 |
promotion_email 不能使用 appointment.* 变量。
validateAgainstSchema() 在保存时校验,_validateVariableContext() 在发送前校验(由 VARIABLE_SCHEMA_VALIDATION feature flag 控制,仅 warn 不阻断)。
{{customer_name}})仍然可用。
legacy-compat.js 在渲染时自动将 ~25 个平面键映射为嵌套格式。
结构化日志记录每次 legacy 变量使用:{ event: 'legacy_variable_used', template_id, flat_keys }
P0 促销 — 创建折扣规则和优惠券
| 类型 | 说明 | 示例 |
|---|---|---|
| Percentage | 百分比折扣 | 20% off |
| Fixed Amount | 固定金额减免 | $10 off |
| Buy X Get Y | 买赠活动 | Buy 2 Get 1 Free |
| Service Bundle | 套餐价 | Manicure + Pedicure $60 |
| 类型 | 使用限制 |
|---|---|
| Single-use | 一次性使用,用完自动失效 |
| Multi-use | 可指定总使用次数上限 |
| Unlimited | 不限使用次数(按有效期控制) |
/admin/marketing/discounts测试: full-flow/02f-discount-crud.spec.ts
测试: full-flow/02f-discount-crud.spec.ts
测试: 未覆盖
P0 沟通 — 创建品牌一致的邮件模板(Schema-Driven 变量系统 v3.0)
GET /api/templates/schemas/:type) 驱动,
支持 4 种模板类型(Service/Promotion/Lifecycle/Transactional),每种类型仅展示其 Schema 中定义的变量。
| Tab | 说明 | 关键组件 |
|---|---|---|
| Email Templates | 代码式邮件模板(HTML + 变量),用于自动化规则 | EmailBuilderEditor |
| SMS Templates | 短信模板,字符计数 + 段数显示 | Textarea + VariableAutocomplete |
| Email Designs | 可视化邮件设计(Canvas/Fabric.js),缩略图画廊 | CanvasEditor, TemplateLibrary |
| Campaigns | 营销活动列表,4 步 Composer 创建流程 | CampaignComposer |
| Triggers | 触发器模板管理 | TriggerTemplatesContent |
| Automation | 自动化规则管理 | AutomationRulesContent |
flowchart TD
A["Promotion → Email Templates tab"] --> B["模板列表"]
B --> C{"操作?"}
C -->|"新建"| D["选择模板类型 (4 种)"]
D -->|"Service"| E1["编辑器: 仅 service_email 变量"]
D -->|"Promotion"| E2["编辑器: 仅 promotion_email 变量"]
D -->|"Lifecycle"| E3["编辑器: 仅 lifecycle_email 变量"]
D -->|"Transactional"| E4["编辑器: 仅 transactional_email 变量"]
E1 --> F["VariableDrawer: Schema-Driven 变量选择器"]
E2 --> F
E3 --> F
E4 --> F
F --> G["插入 Handlebars 变量"]
G --> H["预览 (示例数据)"]
H --> I["发送测试邮件"]
I --> J["保存"]
C -->|"编辑"| F
C -->|"复制"| K["Duplicate 模板"]
style F fill:#00695c,stroke:#004d40,color:#fff
style D fill:#2196F3,stroke:#1565C0,color:#fff
style H fill:#4CAF50,stroke:#388E3C,color:#fff
flowchart TD
A["Promotion → Email Designs tab"] --> B["设计画廊 (缩略图)"]
B -->|"新建"| C["Canvas 编辑器 (Fabric.js)"]
C --> D["拖放元素 + 文本 + 图片"]
D --> E["Canvas 变量选择器"]
E --> F["保存设计"]
F --> G["Promotion → Campaigns tab"]
G -->|"新建 Campaign"| H["Step 1: 选择设计模板"]
H --> I["Step 2: 填写标题/Subject + HTML 内容"]
I --> J["Step 3: 选择收件人 (All/Segment/Manual)"]
J --> K["Step 4: 预览 + 发送/定时"]
K -->|"立即发送"| L["发送进度页 (实时刷新)"]
K -->|"定时发送"| M["Scheduled 状态"]
L --> N["追踪: 打开率/点击率/退订率"]
B -->|"编辑"| C
style C fill:#ad1457,stroke:#880e4f,color:#fff
style H fill:#e65100,stroke:#bf360c,color:#fff
style L fill:#4CAF50,stroke:#388E3C,color:#fff
{{path}}useTemplateVariables(schemaType) hook 获取数据,
hook 调用 GET /api/templates/schemas/:type,API 不可用时 fallback 到静态定义。
marketing:manage 权限,在邮件模板列表service_email Schema 中的分类: guest, appointment, services[], guests[], technician, store, system{{guest.name}} 和 {{appointment.date}}测试: template-variable-schema.spec.ts, template-variable-system.spec.ts
marketing:manage 权限lifecycle_email Schema 的分类: guest (含 birthday, years_as_customer, days_since_visit, preferred_service, loyalty_tier), store, system{{guest.birthday}} 和 {{guest.days_since_visit}}lifecycle_email Schema
测试: template-variable-schema.spec.ts
marketing:manage 权限transactional_email Schema 的分类: guest, transaction (含 items[]), store, system{{#each transaction.items}}...{{/each}} 循环测试: template-variable-schema.spec.ts
promotion_email Schema){{appointment.date}}(service_email 变量)validateAgainstSchema() 检测到 unknown 变量测试: template-variable-schema.spec.ts
variableEngine.buildContextByType('service', ...) 构建变量上下文service-context.js Context Builder 生成嵌套数据测试: 部分覆盖 (API test only)
{{customer_name}} 等平面变量名legacy-compat.js 自动将 customer_name 映射为 guest.name测试: legacy-compat.test.js
P1 触达 — 高打开率的短信通道
测试: 未覆盖
测试: 未覆盖
P0 核心 — 4 步 Campaign Composer 创建并发送邮件活动
flowchart TD
A["Promotion → Campaigns tab"] --> B["活动列表"]
B -->|"新建"| S1
subgraph Composer["Campaign Composer (4-Step Wizard)"]
S1["Step 1: 选择 Email Design 模板"]
S1 --> S2["Step 2: Campaign 名称 + Subject + HTML 内容"]
S2 --> S3["Step 3: 选择收件人"]
S3 --> S4["Step 4: 预览 + 发送/定时"]
end
S3 -->|"All Guests"| S4
S3 -->|"Segment"| S4
S3 -->|"Manual (paste emails)"| S4
S4 -->|"立即发送"| P["发送进度页 (每5秒刷新)"]
S4 -->|"定时发送"| SC["Scheduled (可选 weekly/monthly 循环)"]
P --> T["追踪: 打开率, 点击率, 退订率, 投诉率"]
style S1 fill:#e65100,stroke:#bf360c,color:#fff
style S4 fill:#c62828,stroke:#b71c1c,color:#fff
style P fill:#4CAF50,stroke:#388E3C,color:#fff
style T fill:#1565c0,stroke:#0d47a1,color:#fff
| 状态 | 说明 | 用户可执行操作 |
|---|---|---|
draft | 草稿,尚未发送 | 编辑、删除、发送 |
scheduled | 已设定发送时间 | 编辑、取消 |
active / sending | 正在发送中 | 查看进度、取消 |
completed | 发送完成 | 查看追踪数据、克隆 |
cancelled | 已取消 | 克隆 |
failed | 发送失败 | 查看错误、重试 |
marketing:manage 权限,在 Promotion → Campaigns tab测试: 未覆盖
marketing:manage 权限,在 Step 4 预览页测试: 未覆盖
测试: 未覆盖
P1 效率 — 事件驱动的自动化营销
flowchart LR
subgraph Events["触发事件"]
E1["appointment_booked"]
E2["appointment_reminder"]
E3["appointment_no_show"]
E4["birthday"]
E5["loyalty_milestone"]
end
subgraph Trigger["触发器模板"]
T1["时机: 事件后 X 时间"]
T2["执行时间: 9:00 AM"]
end
subgraph Action["自动化规则"]
A1["选择邮件/SMS 模板"]
A2["选择目标受众"]
end
Events --> Trigger
Trigger --> Action
Action --> SEND["自动发送"]
style SEND fill:#4CAF50,stroke:#388E3C,color:#fff
测试: marketing/rule-management.spec.ts
测试: marketing/rule-management.spec.ts
P1 精准 — 基于行为的自动客户分群
| 类别 (category) | 说明 | 示例规则 |
|---|---|---|
| engagement | 参与度 | 最近 30 天预约 >= 3 次 |
| birthday | 生日相关 | 本月生日的客户 |
| demographics | 人口统计 | 注册超过 1 年 |
| purchase_history | 消费历史 | 累计消费 > $500 |
| membership | 会员状态 | 会员等级 = Gold |
| custom | 自定义 | 任意组合条件 |
/admin/marketing/guest-tagging → Definitions tab测试: 未覆盖
测试: 未覆盖
测试: 未覆盖
P2 数据 — 科学决策的实验框架
flowchart LR
D["Draft 草稿"] -->|"start"| R["Running 运行中"]
R -->|"pause"| P["Paused 暂停"]
P -->|"start"| R
R -->|"complete"| C["Completed 完成"]
D -->|"cancel"| X["Cancelled 取消"]
R -->|"cancel"| X
style D fill:#455a64,stroke:#37474f,color:#fff
style R fill:#2e7d32,stroke:#1b5e20,color:#fff
style C fill:#1565c0,stroke:#0d47a1,color:#fff
| 场景 (scenario) | 说明 |
|---|---|
| inbound_booking | 客户预约转化 |
| inbound_inquiry | 客户咨询转化 |
| outbound_reminder | 预约提醒效果 |
| outbound_recall | 客户召回效果 |
| outbound_promotion | 促销活动效果 |
/admin/marketing/research测试: marketing/research.spec.ts(含 experiments 重定向兼容用例)
/admin/marketing/research/[id]/analytics测试: marketing/research.spec.ts
测试: marketing/research.spec.ts
P2 规划 — 多渠道营销策略编排
| 类型 | 说明 | 典型 KPI |
|---|---|---|
| Acquisition | 获客策略 | 新客户数、首单转化率 |
| Retention | 留存策略 | 复购率、客户生命周期价值 |
| Reactivation | 召回策略 | 沉睡客户回归率 |
| Upsell | 增购策略 | 客单价提升、附加服务率 |
| Referral | 推荐策略 | 推荐转化率、口碑传播系数 |
/admin/marketing/strategies测试: marketing/strategies.spec.ts
P2 洞察 — 收集客户反馈和行为数据
| 类型 | 说明 |
|---|---|
| Survey | 问卷调查 |
| Interview | 深度访谈 |
| Focus Group | 焦点小组讨论 |
| Usability Test | 可用性测试 |
flowchart LR
D["Draft"] --> R["Recruiting 招募中"]
R --> A["Active 进行中"]
A --> C["Completed 完成"]
D --> X["Cancelled"]
R --> X
style A fill:#2e7d32,stroke:#1b5e20,color:#fff
/admin/marketing/research测试: marketing/research.spec.ts
测试: marketing/research.spec.ts
P1 度量 — 营销效果追踪与优化
/admin/marketing/analytics测试: marketing/analytics.spec.ts
| 本模块 CUJ | 依赖模块 | 关系描述 |
|---|---|---|
| I1 折扣 | CUJ-F (Payments) | 折扣在结账流程中应用,影响支付金额 |
| I1 折扣 | CUJ-M (Loyalty) | 会员折扣与促销折扣叠加策略 (best/stack/member_first) |
| I2 邮件模板 | Schema SSOT (049) | 变量选择器由 GET /api/templates/schemas/:type 驱动,4 种 Schema 类型定义可用变量 |
| I4 活动发送 | CUJ-J (Settings) | messaging-config 决定邮件/SMS 供应商 (SES/Resend, Twilio/Telnyx) |
| I5 自动化 | CUJ-B (Appointments) | 预约事件 (booked/reminder/no_show) 触发自动化消息;发送前执行 pre-send validation |
| I6 标签 | CUJ-E (Guests) | 标签结果在客户详情页展示,影响客户分群 |
| I7 实验 | CUJ-H (Reports) | 实验分析结果可纳入营销报表 |
service_email 含 appointment/services/technician,promotion_email 含 campaign,lifecycle_email 含 guest 生命周期字段,transactional_email 含 transaction (items[])。跨类型变量使用在保存时被 validateAgainstSchema() 校验。_validateVariableContext() 检查缺失/未知变量,仅记录结构化警告 (warn-only),不阻断发送。由 VARIABLE_SCHEMA_VALIDATION feature flag 控制。customer_name) 通过 legacy-compat.js 自动映射到嵌套格式 (如 guest.name)。每次 legacy 映射会记录结构化日志。