49c0e5559c
Co-Authored-By: Claude Code <noreply@anthropic.com>
161 lines
8.3 KiB
Markdown
161 lines
8.3 KiB
Markdown
# WhatsApp / Email 联系方式动态配置
|
||
|
||
**日期**: 2026-06-18
|
||
**项目**: AI 客服系统 - VOLT/HESU
|
||
**目标**: 将写死的 WhatsApp 号码和 Email 地址改为通过 `<script>` 标签的 `data-*` 属性动态配置
|
||
|
||
---
|
||
|
||
## 一、设计概述
|
||
|
||
### 1.1 项目背景
|
||
|
||
当前 AI 客服组件([static/widget.js](../../../static/widget.js))和独立聊天页([static/chat.html](../../../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/config.py) / [app/services/email_service.py](../../../app/services/email_service.py) 不在本次范围内——那是服务端逻辑,与浏览器端组件配置无关。
|
||
- 后台管理面板([static/admin.html](../../../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 接入示例
|
||
|
||
```html
|
||
<!-- 嵌入式组件:自定义联系方式 -->
|
||
<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](../../../static/widget.js#L8-L12) 现有 `getAttribute` 调用旁,新增两行(沿用现有写法):
|
||
|
||
```js
|
||
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](../../../static/widget.js#L170)(面板 help-block,含 WhatsApp 与 Email 两个 `href`) | `https://wa.me/+8619037179250` / `mailto:info@borderlesscar.com` | `+ whatsapp +` / `+ email +` |
|
||
| [widget.js:199](../../../static/widget.js#L199)(邀请卡 WhatsApp) | `https://wa.me/+8619037179250` | `+ whatsapp +` |
|
||
| [widget.js:203](../../../static/widget.js#L203)(邀请卡 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"]')`):
|
||
|
||
```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](../../../static/chat.html#L80) 的 `<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](../../../static/chat.html#L80),晚于聊天容器 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](../../../static/widget-test.html#L69) 的组件 `<script>` 标签上添加 `data-whatsapp` / `data-email` 属性,便于本地验证自定义配置生效。
|
||
|
||
---
|
||
|
||
## 四、向后兼容性
|
||
|
||
- 不传任何新属性时:widget.js 与 chat.html 的链接与当前线上**完全一致**(默认值即现有写死值)。
|
||
- 不删除任何现有 `data-*` 配置,不改变现有 DOM 结构、样式或交互。
|
||
- `chat.js` 新增逻辑仅在选中到对应元素时才设置 `href`,对无这两个按钮的页面无副作用。
|
||
|
||
---
|
||
|
||
## 五、验收 / 测试
|
||
|
||
本仓库为纯静态 JS,无自动化测试框架,采用**手动测试清单**(建议补充到 [docs/test-checklist.md](../../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 属性(演示用) |
|