{/* 卡片头部 */}
{/* 排名 */}
{rank}
{/* 标题 */}
{script.title}
{/* 匹配分数 */}
0.8 ? '#f6ffed' : script.score > 0.6 ? '#fffbe6' : '#fff2f0',
color: script.score > 0.8 ? '#52c41a' : script.score > 0.6 ? '#faad14' : '#ff4d4f',
fontSize: 11,
fontWeight: 500,
}}>
{Math.round(script.score * 100)}%匹配
{/* 话术内容 */}
{/* 元数据 */}
📊 成功率{Math.round((script.successRate || 0) * 100)}%
🔥 使用{script.usedCount}次
{script.source === 'LLM_GENERATED' ? '🤖 AI生成' : '📚 话术库'}
{/* 操作按钮 */}
{/* 一键发送 */}
{/* 编辑发送 */}
{/* 取消编辑 */}
{isEditing && (
)}
);
};
export default ScriptCard;
```
#### 4.1.14 TabBar组件
```tsx
// src/components/TabBar.tsx
import React from 'react';
interface TabBarProps {
activeTab: 'recommend' | 'analysis' | 'search';
onChange: (tab: 'recommend' | 'analysis' | 'search') => void;
}
/**
* Tab切换栏
* 智能推荐 / 对话分析 / 话术搜索
*/
const TabBar: React.FC = ({ activeTab, onChange }) => {
const tabs = [
{ key: 'recommend' as const, label: '智能推荐', icon: '💡' },
{ key: 'analysis' as const, label: '对话分析', icon: '📊' },
{ key: 'search' as const, label: '话术搜索', icon: '🔍' },
];
return (
{tabs.map((tab) => (
))}
);
};
export default TabBar;
```
#### 4.1.15 AnalysisPanel组件(对话分析面板)
```tsx
// src/components/AnalysisPanel.tsx
import React from 'react';
import { useProfileStore } from '../stores/useProfileStore';
/**
* 对话分析面板
* 展示对话摘要、意图历史、关键信息等
*/
const AnalysisPanel: React.FC = () => {
const profile = useProfileStore();
return (
{/* 对话摘要 */}
学员为{profile.studentType || '未知类型'},当前处于
{profile.decisionStage || '信息了解'}阶段。
关注重点为{profile.concernFocus || '未明确'},意向度
{profile.intentLevel || '低'}
。
{/* 关键信息 */}
{/* 建议话术方向 */}
{getStageAdvice(profile.decisionStage)}
{/* 风险提示 */}
{profile.intentLevel === '低' && (
⚠️ 当前学员意向度较低,建议耐心引导,先建立信任关系,避免急于推销。
)}
);
};
/**
* 获取阶段建议
*/
function getStageAdvice(stage: string): string {
switch (stage) {
case '开场白':
return '1. 热情问候,建立信任\n2. 了解学员基本信息\n3. 确认学员兴趣方向\n4. 引导进入需求探询阶段';
case '需求探询':
return '1. 深入了解学员背景和目标\n2. 挖掘核心需求\n3. 记录关键信息到画像\n4. 适时引入课程推荐';
case '课程推荐':
return '1. 精准匹配1-2个课程方向\n2. 详细介绍匹配课程的亮点\n3. 用数据支撑推荐\n4. 引导进入价值塑造阶段';
case '价值塑造':
return '1. 强调品牌优势和差异化\n2. 展示成功案例\n3. 提及权威背书(央视报道等)\n4. 消除学员顾虑';
case '报价沟通':
return '1. 明确说明价格\n2. 强调投入产出比\n3. 介绍分期付款方案\n4. 提供限时优惠';
case '异议处理':
return '1. 先认同学员顾虑\n2. 用事实和数据回应\n3. 提供替代方案\n4. 引导回到正向话题';
case '促成报名':
return '1. 制造紧迫感\n2. 明确报名流程\n3. 提供额外优惠\n4. 协助完成报名';
default:
return '根据学员画像和对话上下文,灵活调整话术策略。重点关注学员的核心需求和顾虑点。';
}
}
/**
* 信息项子组件
*/
const InfoItem: React.FC<{ label: string; value: string }> = ({ label, value }) => (
);
/**
* 区块子组件
*/
const Section: React.FC<{ title: string; icon: string; children: React.ReactNode }> = ({
title,
children,
}) => (
);
export default AnalysisPanel;
```
### 4.2 管理后台
管理后台基于React + Ant Design实现,包含话术库管理、数据统计看板等功能。
#### 4.2.1 管理后台路由配置
```typescript
// frontend/admin/src/router.tsx
import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Layout from './components/Layout';
import Dashboard from './pages/Dashboard';
import UtteranceList from './pages/UtteranceList';
import UtteranceEdit from './pages/UtteranceEdit';
import DataStats from './pages/DataStats';
import Settings from './pages/Settings';
/**
* 管理后台路由
*/
const AdminRouter: React.FC = () => (
}>
} />
} />
} />
} />
} />
);
export default AdminRouter;
```
#### 4.2.2 话术库管理页面
```tsx
// frontend/admin/src/pages/UtteranceList.tsx
import React, { useState, useEffect } from 'react';
import { Table, Button, Input, Tag, Space, Modal, message } from 'antd';
import { useNavigate } from 'react-router-dom';
/**
* 话术库管理页面
* 话术列表、搜索、启用/停用、删除
*/
const UtteranceList: React.FC = () => {
const navigate = useNavigate();
const [loading, setLoading] = useState(false);
const [data, setData] = useState([]);
const [keyword, setKeyword] = useState('');
const [pagination, setPagination] = useState({ current: 1, pageSize: 20, total: 0 });
// 加载话术列表
const loadData = async (page: number = 1, pageSize: number = 20) => {
setLoading(true);
try {
const response = await fetch(
`/api/v1/kb/utterances?page=${page}&size=${pageSize}&keyword=${keyword}`
);
const result = await response.json();
if (result.code === 0) {
setData(result.data.list);
setPagination({ ...pagination, current: page, total: result.data.total });
}
} finally {
setLoading(false);
}
};
useEffect(() => { loadData(); }, []);
const columns = [
{ title: '话术ID', dataIndex: 'utteranceId', key: 'utteranceId', width: 180 },
{ title: '标题', dataIndex: 'title', key: 'title', ellipsis: true },
{
title: '阶段',
dataIndex: 'stageTags',
key: 'stageTags',
render: (tags: string) => {
try {
const tagList = JSON.parse(tags);
return tagList.map((t: string) => {t});
} catch { return '-'; }
},
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
render: (status: string) => (
{status === 'ACTIVE' ? '启用' : status === 'DRAFT' ? '草稿' : '停用'}
),
},
{
title: '成功率',
dataIndex: 'successRate',
key: 'successRate',
render: (rate: number) => `${Math.round((rate || 0) * 100)}%`,
},
{ title: '使用次数', dataIndex: 'usedCount', key: 'usedCount' },
{
title: '操作',
key: 'action',
render: (_: any, record: any) => (
),
},
];
const handleDelete = (utteranceId: string) => {
Modal.confirm({
title: '确认删除',
content: `确定要删除话术「${utteranceId}」吗?`,
onOk: async () => {
await fetch(`/api/v1/kb/utterances/${utteranceId}`, { method: 'DELETE' });
message.success('删除成功');
loadData(pagination.current);
},
});
};
return (
setKeyword(e.target.value)}
onSearch={() => loadData(1)}
style={{ width: 300 }}
/>
loadData(p.current, p.pageSize)}
/>
);
};
export default UtteranceList;
```
---
## 第五部分:企微集成配置指南
### 5.1 企微后台配置步骤
#### 5.1.1 注册企业微信
1. 访问 https://work.weixin.qq.com/ 注册企业
2. 完成企业认证(可选,但认证后功能更完整)
3. 获取企业ID(CorpID)- 在「我的企业」→「企业ID」中查看
#### 5.1.2 创建自建应用
1. 进入「应用管理」
2. 点击「创建应用」
3. 填写应用信息:
- 应用名称:AI话术助手
- 应用Logo:上传应用图标
- 可见范围:选择需要使用的部门/人员
4. 创建完成后记录:
- AgentId
- Secret(点击「查看」获取)
#### 5.1.3 配置可信域名
1. 进入应用详情页 →「网页授权及JS-SDK」
2. 点击「设置可信域名」
3. 填写域名:
- 申请校验域名(下载校验文件上传到服务器根目录)
- 或者使用已备案域名,上传校验文件验证
4. 同时配置「授权回调域」(用于OAuth登录)
#### 5.1.4 申请会话内容存档
1. 进入「管理工具」→「会话内容存档」
2. 点击「开通」并选择开通范围(全部或部分成员)
3. 开通后获取:
- 企业ID(CorpID)
- 存档Secret(在「会话内容存档」→「API」中获取)
4. 下载C SDK(按操作系统选择Linux/Windows版本)
#### 5.1.5 配置聊天工具栏
1. 进入「客户联系」→「加客户」→「聊天工具栏」
2. 点击「配置应用页面」
3. 选择刚才创建的「AI话术助手」应用
4. 配置页面参数:
- 页面名称:AI话术助手
- 页面URL:https://your-domain.com/sidebar/
- 点击「确定」保存
#### 5.1.6 配置回调URL
1. 进入「管理工具」→「会话内容存档」→「API」
2. 配置回调:
- 回调URL:https://your-domain.com/api/v1/archive/callback
- Token:随机生成16位字符串
- EncodingAESKey:点击「随机获取」
3. 记录Token和EncodingAESKey(后端配置需要)
### 5.2 RSA密钥生成与配置
#### 5.2.1 生成RSA密钥对
```bash
# 使用OpenSSL生成2048位RSA密钥对
# 1. 生成私钥(PKCS#1格式,企微要求)
openssl genrsa -out private_key.pem 2048
# 2. 从私钥提取公钥
openssl rsa -in private_key.pem -pubout -out public_key.pem
# 3. 将公钥转为Base64(上传到企微后台)
base64 -w 0 public_key.pem > public_key_base64.txt
# 4. 查看私钥(妥善保存,不要泄露)
cat private_key.pem
# 5. 查看公钥Base64
cat public_key_base64.txt
```
#### 5.2.2 上传公钥到企微后台
1. 进入「管理工具」→「会话内容存档」→「API」
2. 找到「公钥配置」
3. 将 public_key_base64.txt 的内容粘贴进去
4. 点击「保存」
#### 5.2.3 私钥存储到服务器
```bash
# 1. 创建密钥目录
mkdir -p /opt/ai-assistant/keys
chmod 700 /opt/ai-assistant/keys
# 2. 将私钥复制到服务器
cp private_key.pem /opt/ai-assistant/keys/
chmod 600 /opt/ai-assistant/keys/private_key.pem
# 3. 设置环境变量(在docker-compose.yml或启动脚本中)
export ARCHIVE_RSA_PRIVATE_KEY_PATH=/opt/ai-assistant/keys/private_key.pem
# 或者将私钥内容直接作为环境变量(不推荐,太长)
# export ARCHIVE_RSA_PRIVATE_KEY=$(cat /opt/ai-assistant/keys/private_key.pem)
```
### 5.3 JS-SDK配置代码
#### 5.3.1 后端签名生成接口
```java
package com.artedu.auth.controller;
import org.springframework.web.bind.annotation.*;
import java.security.MessageDigest;
import java.util.Formatter;
import java.util.UUID;
/**
* 企微JS-SDK签名接口
*/
@RestController
@RequestMapping("/api/v1/auth")
public class JsSdkSignatureController {
/**
* 获取JS-SDK签名
* 前端调用ww.register时需要
*/
@GetMapping("/signature")
public Result