Files
ai-kefu-jc/docs/superpowers/specs/2026-06-18-dynamic-contact-config-design.md
2026-09-29 14:15:12 +08:00

8.3 KiB
Raw Permalink Blame History

WhatsApp / Email 联系方式动态配置

日期: 2026-06-18 项目: AI 客服系统 - VOLT/HESU 目标: 将写死的 WhatsApp 号码和 Email 地址改为通过 <script> 标签的 data-* 属性动态配置


一、设计概述

1.1 项目背景

当前 AI 客服组件(static/widget.js)和独立聊天页(static/chat.html)中的 WhatsApp 跳转链接和 Email 链接是固定写死在源码里的:

  • WhatsApp:https://wa.me/+8619037179250
  • Email:mailto:info@borderlesscar.com

这些值是 borderlesscar 这一个部署的专属联系方式。当组件需要复用到其它品牌/站点时,必须改源码、重新部署,无法按部署点灵活配置。

1.2 设计目标

  • 接入方在引入 <script> 标签时,可通过 data-whatsapp、data-email 属性传入自己的联系方式。
  • 完全向后兼容:不传任何属性时,行为与现在线上完全一致(回退到现有默认值)。
  • 复用组件已有的 data-* 配置机制(data-position / data-theme / data-title / data-auto-open 已经走这条路径),不引入新的配置范式。
  • 嵌入式组件(widget.js)和独立页(chat.html)使用同一套配置约定,只需学习一种机制。

1.3 非目标(Out of Scope)

  • 后端 .env / app/config.py / app/services/email_service.py 不在本次范围内——那是服务端逻辑,与浏览器端组件配置无关。
  • 后台管理面板(static/admin.html)里展示的联系方式是 AI 从对话中抽取的数据,不属于本次「部署级配置」范畴,不改。
  • 不做按钮显隐配置(即不引入「未配置则隐藏按钮」的能力)。本次确认的策略是「未配置则回退默认值」。

二、配置约定(契约)

2.1 属性定义

属性 含义 取值格式 默认值(未提供时)
data-whatsapp WhatsApp 联系方式跳转链接 完整 URL,如 https://wa.me/8619037179250 https://wa.me/+8619037179250
data-email Email 联系方式链接 完整 URL,如 mailto:sales@example.com mailto:info@borderlesscar.com

2.2 取值格式说明

采用完整 URL 而非「只写号码/邮箱」:

  • 组件内部不做协议拼接,直接把属性值作为 <a href> 使用。
  • 更灵活:WhatsApp 将来可换成非 wa.me 的跳转地址,Email 也可带 ?subject= 等参数。
  • 接入方需自行保证带上协议前缀(https:// / mailto:)。

2.3 缺省 / 空值处理

  • 属性缺失:使用上表默认值。
  • 属性为空字符串(data-whatsapp=""):与缺失等价,使用默认值。
  • 不存在「隐藏按钮」的语义——本次范围内联系方式按钮始终展示。

2.4 接入示例

<!-- 嵌入式组件:自定义联系方式 -->
<script
  src="https://chat.example.com/static/widget.js"
  data-position="bottom-right"
  data-theme="light"
  data-whatsapp="https://wa.me/8613800138000"
  data-email="mailto:support@mybrand.com"
></script>

<!-- 独立页 chat.html:同样在它的 chat.js script 标签上传参 -->
<script
  src="/static/js/chat.js"
  data-whatsapp="https://wa.me/8613800138000"
  data-email="mailto:support@mybrand.com"
></script>

三、改动详情

3.1 static/widget.js(嵌入式组件)

读取配置:在 widget.js:8-12 现有 getAttribute 调用旁,新增两行(沿用现有写法):

var whatsapp = script.getAttribute("data-whatsapp") || "https://wa.me/+8619037179250";
var email    = script.getAttribute("data-email")    || "mailto:info@borderlesscar.com";

使用配置:把以下 3 处写死的 href 替换为字符串拼接 + whatsapp + / + email +:

位置 当前写死值 改为
widget.js:170(面板 help-block,含 WhatsApp 与 Email 两个 href) https://wa.me/+8619037179250 / mailto:info@borderlesscar.com + whatsapp + / + email +
widget.js:199(邀请卡 WhatsApp) https://wa.me/+8619037179250 + whatsapp +
widget.js:203(邀请卡 Email) mailto:info@borderlesscar.com + email +

注意:第 170 行是单行内同时包含 WhatsApp 与 Email 两个 <a>,需保证两处拼接都正确,不要漏改其中一个。

3.2 static/js/chat.js + static/chat.html(独立页,方案 A)

chat.html 是独立整页,加载 /static/js/chat.js(不加载 widget.js)。为保持与组件同一套配置机制,让 chat.js 读取自身 <script> 标签上的 data-whatsapp / data-email 并应用到页面两个锚点上。

static/js/chat.js 改动:

  • 在 IIFE 顶部,获取自身 script 标签并读取配置(与 widget.js 同样的 document.currentScript 写法;为兼容异步加载,回退用 querySelector('script[src*="chat.js"]')):
var chatScript = document.currentScript || document.querySelector('script[src*="chat.js"]');
var whatsapp = (chatScript && chatScript.getAttribute("data-whatsapp")) || "https://wa.me/+8619037179250";
var email    = (chatScript && chatScript.getAttribute("data-email"))    || "mailto:info@borderlesscar.com";

// 应用到页面两个锚点
var waBtn = document.querySelector('.whatsapp-btn');
var emBtn = document.querySelector('.email-btn');
if (waBtn) waBtn.href = whatsapp;
if (emBtn) emBtn.href = email;

static/chat.html 改动:

  • 在 chat.html:80 的 <script src="/static/js/chat.js"></script> 标签上添加 data-whatsapp / data-email 属性,使演示页展示配置能力。
  • 第 35、39 行原有的静态 href 保留为默认值不动,作为 chat.js 执行前的 fallback(避免 JS 未执行时出现空链接),chat.js 启动后会按配置覆盖。
  • 执行时序安全:chat.js 在 <body> 末尾加载(chat.html:80,晚于聊天容器 DOM),故 IIFE 顶部同步 querySelector('.whatsapp-btn' / '.email-btn') 时两个锚点已存在,同步赋值 href 安全。这两个 class 仅出现在 chat.html 的 light DOM 中(widget.js 里同名 class 在其 shadow DOM 内,互不干扰)。

3.3 static/widget-test.html(组件测试/演示页)

  • 在 widget-test.html:69 的组件 <script> 标签上添加 data-whatsapp / data-email 属性,便于本地验证自定义配置生效。

四、向后兼容性

  • 不传任何新属性时:widget.js 与 chat.html 的链接与当前线上完全一致(默认值即现有写死值)。
  • 不删除任何现有 data-* 配置,不改变现有 DOM 结构、样式或交互。
  • chat.js 新增逻辑仅在选中到对应元素时才设置 href,对无这两个按钮的页面无副作用。

五、验收 / 测试

本仓库为纯静态 JS,无自动化测试框架,采用手动测试清单(建议补充到 docs/test-checklist.md):

  1. 默认值(不传属性):widget-test.html 与 chat.html 的 WhatsApp / Email 按钮分别指向 wa.me/+8619037179250 与 mailto:info@borderlesscar.com,与改动前一致。
  2. 自定义值:在 widget-test.html 组件 script 标签上传入自定义 data-whatsapp / data-email,组件内三处链接(面板 help-block、邀请卡 WhatsApp、邀请卡 Email)均指向新地址。
  3. chat.html 自定义值:在 chat.js script 标签上传入自定义值,独立页两个按钮指向新地址。
  4. 空字符串:data-whatsapp="" 等价于未传,回退默认值。
  5. 禁用 JS:chat.html 在 JS 未执行时,静态 href 仍为默认值(不出现空链接)。

六、影响文件清单

文件 改动类型
static/widget.js 读取 2 个新属性 + 替换 3 处 href
static/js/chat.js 新增读取自身 script 标签配置 + 设置 2 个锚点 href
static/chat.html chat.js script 标签加 2 个 data 属性(静态 href 保留为默认)
static/widget-test.html 组件 script 标签加 2 个 data 属性(演示用)